secret和configmap資源都是通過掛載的方式將對應資料掛載到容器內部環境中去使用,兩者的使用沒有太多的不同 ,configmap資源通常用於為pod提供組態檔;secret資源主要用於為pod提供證書、使用者名稱密碼等敏感資料;
Configmap將非機密性資訊(如設定資訊)和映象解耦, 實現方式為將設定資訊放到configmap物件中,然後在pod的中作為Volume掛載到pod中,從而實現匯入設定的目的。
Secret 的功能類似於 ConfigMap給pod提供額外的設定資訊,但是Secret是一種包含少量敏感資訊例如密碼、令牌或金鑰的物件。Secret 的名稱必須是合法的 DNS 子域名。每個Secret的大小最多為1MiB,主要是為了避免使用者建立非常大的Secret進而導致API伺服器和kubelet記憶體耗盡,不過建立很多小的Secret也可能耗盡記憶體,可以使用資源配額來約束每個名稱空間中Secret的個數。在通過yaml檔案建立secret時,可以設定data或stringData欄位,data和stringData欄位都是可選的,data欄位中所有鍵值都必須是base64編碼的字串,如果不希望執行這種 base64字串的轉換操作,也可以選擇設定stringData欄位,其中可以使用任何非加密的字串作為其取值。
首先使用者向apiserver提交建立secret資源的請求;apiserver收到使用者的資源建立請求,通過apiserver的認證授權、准入控制後,apiserver會將建立好的secret資訊存放在etcd中;隨後使用者在建立pod中呼叫了掛載某個secret以後,對應在pod建立時會被pause容器將對應secret資源中的data資料載入至對應pod中,從而實現讓向pod內部傳遞敏感資料的目的;
Kubernetes預設支援多種不同型別的secret,用於一不同的使用場景,不同型別的secret的設定引數也不一樣。
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
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中沒有生效;
解決辦法
進入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;
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
data:
host: "172.31.7.189"
username: "user1"
password: "12345678"
應用上述設定清單,建立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直接指定鍵值的環境變數;
openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 3560 -nodes -subj '/CN=www.ca.com'
openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=www.mysite.com'
openssl x509 -req -sha256 -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt
kubectl create secret tls myserver-tls-key --cert=./server.crt --key=./server.key
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是否可以正常存取?
kubectl create secret docker-registry harbor.ik8s.cc-imagepull \
--docker-server=harbor.ik8s.cc \
--docker-username=admin \
--docker-password=123456
登入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詳細資訊
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正常跑起來