Configmap和Secret資源介紹
secret和configmap資源都是通過掛載的方式將對應數據掛載到容器內部環境中去使用,兩者的使用沒有太多的不同 ,configmap資源通常用於爲pod提供配置文件;secret資源主要用於爲pod提供證書、用戶名密碼等敏感數據;
configmap資源
Configmap將非機密性信息(如配置信息)和鏡像解耦, 實現方式爲將配置信息放到configmap對象中,然後在pod的中作爲Volume掛載到pod中,從而實現導入配置的目的。
ConfigMap資源使用場景
- 通過Configmap給pod中的容器服務提供配置文件,配置文件以掛載到容器的形式使用。
- 通過Configmap給pod定義全局環境變量。
- 通過Configmap給pod傳遞命令行參數,如mysql -u -p中的賬戶名密碼可以通過Configmap傳遞。
注意事項
- Configmap需要在pod使用它之前創建。
- pod只能使用位於同一個namespace的Configmap,即Configmap不能跨namespace使用。
- 通常用於非安全加密的配置場景。
- Configmap通常是小於1MB的配置。
secret資源
Secret 的功能類似於 ConfigMap給pod提供額外的配置信息,但是Secret是一種包含少量敏感信息例如密碼、令牌或密鑰的對象。Secret 的名稱必須是合法的 DNS 子域名。每個Secret的大小最多爲1MiB,主要是爲了避免用戶創建非常大的Secret進而導致API服務器和kubelet內存耗盡,不過創建很多小的Secret也可能耗盡內存,可以使用資源配額來約束每個名字空間中Secret的個數。在通過yaml文件創建secret時,可以設置data或stringData字段,data和stringData字段都是可選的,data字段中所有鍵值都必須是base64編碼的字符串,如果不希望執行這種 base64字符串的轉換操作,也可以選擇設置stringData字段,其中可以使用任何非加密的字符串作爲其取值。
Secret資源使用流程
首先用戶向apiserver提交創建secret資源的請求;apiserver收到用戶的資源創建請求,通過apiserver的認證授權、准入控制後,apiserver會將創建好的secret信息存放在etcd中;隨後用戶在創建pod中調用了掛載某個secret以後,對應在pod創建時會被pause容器將對應secret資源中的data數據加載至對應pod中,從而實現讓向pod內部傳遞敏感數據的目的;
Secret資源使用場景
- 作爲掛載到一個或多個容器上的卷 中的文件(crt文件、key文件)。
- 作爲容器的環境變量。
- 由 kubelet 在爲 Pod 拉取鏡像時使用(與鏡像倉庫的認證)。
Secret資源類型簡介
Kubernetes默認支持多種不同類型的secret,用於一不同的使用場景,不同類型的secret的配置參數也不一樣。
configmap資源使用示例
基於configmap給nginx pod提供自定義的server配置
1.1、創建configmap資源
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
mysite: |
server {
listen 80;
server_name www.mysite.com;
index index.html index.php index.htm;
location / {
root /data/nginx/mysite;
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
}
}
}
myserver: |
server {
listen 80;
server_name www.myserver.com;
index index.html index.php index.htm;
location / {
root /data/nginx/myserver;
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
}
}
}
data字段中的mysite和myserver是用來標識不同配置信息的,即該名稱用於pod掛載configmap資源時被引用的名稱;
應用資源配置清單
kubectl apply -f nginx-configmap-demo.yaml
驗證configmap資源
kubectl get cm
kubectl describe cm nginx-config
1.2、創建pod使用使用掛載configmap
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: ng-deploy-80
template:
metadata:
labels:
app: ng-deploy-80
spec:
containers:
- name: ng-deploy-80
image: harbor.ik8s.cc/baseimages/nginx:1.20.0
ports:
- containerPort: 80
volumeMounts:
- mountPath: /data/nginx/mysite
name: nginx-mysite-statics
- mountPath: /data/nginx/myserver
name: nginx-myserver-statics
- name: nginx-mysite-config
mountPath: /etc/nginx/conf.d/mysite/
- name: nginx-myserver-config
mountPath: /etc/nginx/conf.d/myserver/
volumes:
- name: nginx-mysite-config
configMap:
name: nginx-config
items:
- key: mysite
path: mysite.conf
- name: nginx-myserver-config
configMap:
name: nginx-config
items:
- key: myserver
path: myserver.conf
- name: nginx-myserver-statics
nfs:
server: 192.168.0.42
path: /data/k8sdata/myserver
- name: nginx-mysite-statics
nfs:
server: 192.168.0.42
path: /data/k8sdata/mysite
---
apiVersion: v1
kind: Service
metadata:
name: ng-deploy-80
spec:
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30019
protocol: TCP
type: NodePort
selector:
app: ng-deploy-80
上述配置清單主要定義了一個deploy類型的控制器和nodeport類型的service,其中deploy控制器定義了一個nginx pod 掛載使用nfs服務上的靜態資源和掛載使用configmap給nginx提供配置;service主要定義了通過標籤選擇器來匹配pod來實現將用戶請求的流量轉發至後端nginx pod;
在nfs服務器上準備靜態資源目錄
在nfs服務器上創建靜態資源
應用配置清單創建pod使用configmap資源和掛載nfs服務器上的靜態資源
kubectl apply -f nginx-dep-demo.yaml
驗證,查看pod配置信息是否正常被pod掛載?
可以看到pod正常掛載configmap中指定的配置信息;
在k8s集羣節點任意節點上修改hosts文件來解析域名
在k8s的節點上將對應域名指向集羣任意節點地址上即可
訪問nginx,看看對應nfs靜態資源是否能夠正常被訪問到?
這裏雖然能夠正常被訪問nginx主頁,但是不是我們想要的頁面,這其中的原因是,我們把nginxpod的配置文件掛載的路徑沒有在nginx.conf中導入,導致我們掛載的配置在nginx中沒有生效;
解決辦法
- 進入pod內部,修改nginx.conf配置文件 (臨時生效,pod重建失效,不推薦)
- 在製作鏡像時,直接將主配置文件寫好,再製作好鏡像;(推薦)
- 使用configmap資源將導入nginx配置再此掛載至/etc/nginx/conf.d/目錄下;(默認nginx只導入了/etc/nginx/conf.d/*.conf,我們只需要將導入配置以.conf結尾的配置文件掛載至/etc/nginx/conf.d/目錄下即可)
進入nginxpod,修改主配置文件
這裏主要加上導入/etc/nginx/conf.d/下子目錄下的.conf結尾的配置文件,讓/etc/nginx/conf.d/myserver/myserver.conf和/etc/nginx/conf.d/mysite/mysite.conf配置文件被nginx加載;
驗證:使用不同域名訪問nginx看看是否能夠訪問到對應不同的靜態資源?
現在使用不同域名的方式訪問nginx就可以訪問到不同站點的資源了;生產中會通過前端一個負載均衡器來反向代理nodeport類型的service;
基於configmap給pod提供自定義環境變量
1.1、創建configmap資源
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
host: "172.31.7.189"
username: "user1"
password: "12345678"
應用上述配置清單,創建configmap資源
1.2、創建pod使用configmap資源
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: ng-deploy-80
template:
metadata:
labels:
app: ng-deploy-80
spec:
containers:
- name: ng-deploy-80
image: harbor.ik8s.cc/baseimages/nginx:1.20.0
env:
- name: HOST
valueFrom:
configMapKeyRef:
name: nginx-config
key: host
- name: USERNAME
valueFrom:
configMapKeyRef:
name: nginx-config
key: username
- name: PASSWORD
valueFrom:
configMapKeyRef:
name: nginx-config
key: password
######
- name: "password"
value: "123456"
ports:
- containerPort: 80
向pod內部傳遞環境變量的方式有兩種,一種是通過env字段來引用configmap資源,使用name字段來指定環境變量名稱,使用valueFrom字段來指定對應環境變量值的來源;configMapKeyRef字段表示使用configmap資源來向對應環境變量賦值;name是指定configmap的名稱,key是用來指定configmap中對應key;另外一種就是使用env字段,通過列表的方式直接向pod傳遞鍵值環境變量;
應用配置清單
可以看到創建的pod內部有我們再configmap中定義的環境變量,也有我們通過env直接指定鍵值的環境變量;
secret資源使用示例
基於自定義的Secret實現Nginx https認證
1、自簽名證書製作
1.1、生成自簽名CA證書
openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 3560 -nodes -subj '/CN=www.ca.com'
1.2、生成自簽名證書私鑰和CSR
openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=www.mysite.com'
1.3、用自簽名CA證書籤發自簽名證書csr生成自簽名證書crt
openssl x509 -req -sha256 -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
2、基於自簽名證書在k8s上創建secret資源
kubectl create secret tls myserver-tls-key --cert=./server.crt --key=./server.key
3、創建nginx配置清單使用secret
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
default: |
server {
listen 80;
server_name www.mysite.com;
listen 443 ssl;
ssl_certificate /etc/nginx/conf.d/certs/tls.crt;
ssl_certificate_key /etc/nginx/conf.d/certs/tls.key;
location / {
root /usr/share/nginx/html;
index index.html;
if ($scheme = http ){ #未加條件判斷,會導致死循環
rewrite / https://www.mysite.com permanent;
}
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
}
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-frontend-deployment
spec:
replicas: 1
selector:
matchLabels:
app: myserver-myapp-frontend
template:
metadata:
labels:
app: myserver-myapp-frontend
spec:
containers:
- name: myserver-myapp-frontend
image: harbor.ik8s.cc/baseimages/nginx:1.20.0
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d/myserver
- name: myserver-tls-key
mountPath: /etc/nginx/conf.d/certs
volumes:
- name: nginx-config
configMap:
name: nginx-config
items:
- key: default
path: mysite.conf
- name: myserver-tls-key
secret:
secretName: myserver-tls-key
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-frontend
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30018
protocol: TCP
- name: htts
port: 443
targetPort: 443
nodePort: 30019
protocol: TCP
selector:
app: myserver-myapp-frontend
上述配置清單主要創建了一個configmap資源,用來給nginxpod提供配置信息,然後創建了一個deploy控制器運行了一個nginx pod ,這個pod掛載使用configmap和secret資源;最後創建了一個service將對應nginx Pod服務暴露給集羣外部客戶端訪問;
應用配置清單
驗證:進入pod內部,查看對應配置信息和證書文件是否正常掛載?
可以看到我們創建configmap資源中的配置信息和secret資源中的證書信息都正常掛載至nginx pod對應指定目錄下
修改nginx主配置文件,讓其加載我們通過configmap掛載的配置文件
重載nginx pod配置文件
上述方法不推薦,正確的做法就是在打鏡像的時候,將對應配置文件打入鏡像;或者我們使用configmap將對應配置信息創建爲configmap資源對象,然後再pod中掛載對應配置信息即可;
驗證:訪問集羣任意節點30018端口和30019端口,看看對應nginx pod是否能夠正常被訪問?是否是加密訪問呢?
從上面的訪問情況可以看到,直接訪問30019,會報400,這是因爲30019時一個https的端口,用http的協議去訪問肯定不能正常響應;當我們訪問30018時,對應頁面會進行跳轉到https://www.mysite.com,這是因爲我們在nginx的配置中配置了訪問http端口進行重定向https://www.mysite.com;訪問30019端口時,用https協議訪問30019時,也正常加載了證書;
使用configmap將nginx配置信息導入主配置文件
apiVersion: v1
kind: ConfigMap
metadata:
name: include-conf
data:
include.conf: |
include /etc/nginx/conf.d/*/*.conf;
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
default: |
server {
listen 80;
server_name www.mysite.com;
listen 443 ssl;
ssl_certificate /etc/nginx/conf.d/certs/tls.crt;
ssl_certificate_key /etc/nginx/conf.d/certs/tls.key;
location / {
root /usr/share/nginx/html;
index index.html;
if ($scheme = http ){ #未加條件判斷,會導致死循環
rewrite / https://www.mysite.com permanent;
}
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
}
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myserver-myapp-frontend-deployment-v1
spec:
replicas: 1
selector:
matchLabels:
app: myserver-myapp-frontend-v1
template:
metadata:
labels:
app: myserver-myapp-frontend-v1
spec:
containers:
- name: myserver-myapp-frontend-v1
image: harbor.ik8s.cc/baseimages/nginx:1.20.0
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d/myserver
- name: myserver-tls-key
mountPath: /etc/nginx/conf.d/certs
- name: include-conf
mountPath: /etc/nginx/conf.d
volumes:
- name: nginx-config
configMap:
name: nginx-config
items:
- key: default
path: mysite.conf
- name: myserver-tls-key
secret:
secretName: myserver-tls-key
- name: include-conf
configMap:
name: include-conf
items:
- key: include.conf
path: include.conf
---
apiVersion: v1
kind: Service
metadata:
name: myserver-myapp-frontend-v1
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 31080
protocol: TCP
- name: htts
port: 443
targetPort: 443
nodePort: 31443
protocol: TCP
selector:
app: myserver-myapp-frontend-v1
pod掛載使用configmap時,對應pod內部必須事先不存在對應文件,如果對應文件存在,則對應pod會啓不起來;所以我們掛載configmap時指定掛載至/etc/nginx/conf.d即可;
應用配置清單,看看使用https訪問31443是否可以正常訪問?
基於自定義的Secret實現私有鏡像的下載認證
創建secret資源
方式一:通過命令創建
kubectl create secret docker-registry harbor.ik8s.cc-imagepull \
--docker-server=harbor.ik8s.cc \
--docker-username=admin \
--docker-password=123456
方式二:通過docker/containerd認證文件創建
登錄harbor,生成config.json文件
使用config.json文件創建secret資源
kubectl create secret generic harbor.k8s.cc-registry-image-pull-key \
--from-file=.dockerconfigjson=/root/.docker/config.json \
--type=kubernetes.io/dockerconfigjson
在harbor上將baseimgaes倉庫設置爲私有倉庫
驗證,使用docker/containerd拉取harbor.k8s.cc/baseimages下的鏡像,看看是否可以正常拉取?
可以看到現在更改倉庫爲私有倉庫以後,對應倉庫中的鏡像不可以正常被拉取
驗證,使用私有倉庫鏡像創建pod,看看pod是否能夠正常運行起來?
apiVersion: v1
kind: Pod
metadata:
name: "tomcat-demo"
namespace: default
labels:
app: "tomcat-demo"
spec:
containers:
- name: tomcat-demo
image: "harbor.ik8s.cc/baseimages/tomcat:v1"
ports:
- containerPort: 8080
name: http
應用配置清單,看看對應pod是否能夠正常跑起來?
可以看到對應pod處於ErrImagePull狀態,該狀態就是表示pod在創建時,下載鏡像錯誤
查看pod詳細信息
創建pod使用secret
apiVersion: v1
kind: Pod
metadata:
name: "tomcat-demo"
namespace: default
labels:
app: "tomcat-demo"
spec:
containers:
- name: tomcat-demo
image: "harbor.ik8s.cc/baseimages/tomcat:v1"
imagePullPolicy: Always
ports:
- containerPort: 8080
name: http
imagePullSecrets:
- name: harbor.k8s.cc-registry-image-pull-key
spec字段中使用imagePullSecrets字段來引用dockerconfigjson類型的secret資源,使用name字段指定secret的名稱即可
驗證pod運行狀態
應用配置清單,看看對應pod是否能夠正常跑起來?
可以看到現在對應pod正常跑起來