Kubernetes 的用法和解析 -- 3

一.Secret 实现

1.1 secret  详解

secret用来保存小片敏感数据的k8s资源,例如密码,token,或者秘钥。这类数据当然也可以存放在Pod或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,并减少暴露的风险。
 
 用户可以创建自己的secret,系统也会有自己的secret。
 Pod需要先引用才能使用某个secret

Pod使用secret方式:

作为volume的一个域被一个或多个容器挂载 

內建的Secrets:

由ServiceAccount创建的API证书附加的秘钥k8s自动生成的用来访问apiserver的Secret,所有Pod会默认使用这个Secret与apiserver通信 

创建自己的Secret:

方式1:使用kubectl create secret命令
方式2:yaml文件创建Secret 

1.2 secret 使用

创建Secret

假如某个Pod要访问数据库,需要用户名密码,现在我们分别设置这个用户名和密码 Secret 对象要求这些数据必须是经过 Base64 转码的,以免出现明文密码显示的安全隐患。

# 创建一个secret.yaml文件,内容用base64编码:明文显示容易被别人发现,这里先转码。
[root@kub-k8s-master ~]# echo -n 'admin' | base64
YWRtaW4=
[root@kub-k8s-master ~]# echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm

创建一个secret.yaml文件,内容用base64编码

[root@kub-k8s-master prome]# vim secret.yml
---
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque  #模糊
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

 创建:

[root@kub-k8s-master prome]# kubectl apply -f secret.yml 
secret/mysecret created

 解析Secret中内容,还是经过编码的---需要解码

# 查看secret
[root@kub-k8s-master ~]# kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-7vc82   kubernetes.io/service-account-token   3      30h
mysecret              Opaque                                2      6s

# 查看secret详细信息
[root@kub-k8s-master prome]# kubectl get secret mysecret -o yaml
apiVersion: v1
data:
  password: MWYyZDFlMmU2N2Rm
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2023-10-21T03:07:56Z"
  name: mysecret
  namespace: default
  resourceVersion: "162855"
  selfLink: /api/v1/namespaces/default/secrets/mysecret
  uid: 36bcd07d-92eb-4755-ac0a-a5843ed986dd
type: Opaque

手动base64解码方式:

[root@kub-k8s-master ~]# echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
1.3 使用Secret

secret可以作为数据卷挂载或者作为环境变量暴露给Pod中的容器使用,也可以被系统中的其他资源使用。 

一个Pod中引用Secret的列子:

创建一个Secret,多个Pod可以引用同一个Secret

修改Pod的定义,在spec.volumes[]加一个volume,给这个volume起个名字,spec.volumes[].secret.secretName记录的是要引用的Secret名字

[root@kub-k8s-master prome]# vim pod_use_secret.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: testredis
    image: daocloud.io/library/redis
    volumeMounts:    #挂载一个卷
    - name: foo     #这个名字需要与定义的卷的名字一致
      mountPath: "/etc/foo"  #挂载到容器里哪个目录下,随便写
      readOnly: true
  volumes:     #数据卷的定义
  - name: foo   #卷的名字这个名字自定义
    secret:    #卷是直接使用的secret。
      secretName: mysecret   #调用刚才定义的secret
      
创建:
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml 
pod/mypod created
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash
root@mypod:/data# cd /etc/foo/
root@mypod:/etc/foo# ls
password  username
root@mypod:/etc/foo# cat password 
1f2d1e2e67df

结果中看到,保存在 Etcd 里的用户名和密码信息,已经以文件的形式出现在了容器的 Volume 目录里。
而这个文件的名字,就是 kubectl create secret 指定的 Key,或者说是 Secret 对象的 data 字段指定的 Key。

每一个被引用的Secret都要在spec.volumes中定义
 如果Pod中的多个容器都要引用这个Secret那么每一个容器定义中都要指定自己的volumeMounts,但是Pod定义中声明一次spec.volumes就好了。 

映射secret key到指定的路径

可以控制secret key被映射到容器内的路径,利用spec.volumes[].secret.items来修改被映射的具体路径

[root@kub-k8s-master prome]# kubectl delete -f pod_use_secret.yaml 
pod "mypod" deleted
[root@kub-k8s-master prome]# vim pod_use_secret.yaml
---
apiVersion: v1
kind: Pod
metadata:
 name: mypod
spec:
 containers:
 - name: testredis
   image: daocloud.io/library/redis
   volumeMounts:
   - name: foo
     mountPath: "/etc/foo"
     readOnly: true
 volumes:
 - name: foo
   secret:
     secretName: mysecret
     items:   #定义一个items
      - key: username   #将那个key重新定义到那个目录下
        path: my-group/my-username  #相对路径,相对于/etc/foo的路径
       
2.创建
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml 
pod/mypod created
3.从volume中读取secret的值
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash                         
root@mypod:/data# cd /etc/foo/my-group
root@mypod:/etc/foo/my-group# ls
my-username
root@mypod:/etc/foo/my-group# cat my-username 
admin
root@mypod:/etc/foo/my-group#

username被映射到了文件/etc/foo/my-group/my-username而不是/etc/foo/username,而password没有被使用,这种方式每个key的调用需要单独用key像username一样调用

被挂载的secret内容自动更新

也就是如果修改一个Secret的内容,那么挂载了该Secret的容器中也将会取到更新后的值,但是这个时间间隔是由kubelet的同步时间决定的。

1.设置base64加密
[root@kub-k8s-master prome]# echo mahong | base64
bWFob25n
2.将admin替换成mahong
[root@kub-k8s-master prome]# vim secret.yml
---
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: bWFob25n   #修改为mahong的base64加密后的
  password: MWYyZDFlMmU2N2Rm
  
1.创建
[root@kub-k8s-master prome]# kubectl apply -f secret.yml 
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
secret/mysecret configured
2.连接pod容器
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash
root@mypod:/data# cd /etc/foo/my-group
root@mypod:/etc/foo/my-group# ls
my-username
root@mypod:/etc/foo/my-group# cat my-username 
mahong

 以环境变量的形式使用Secret

[root@kub-k8s-master prome]# kubectl delete -f pod_use_secret.yaml 
pod "mypod" deleted
[root@kub-k8s-master prome]# vim pod_use_secret.yaml
---
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: testredis
    image: daocloud.io/library/redis
    env:  #定义环境变量
     - name: SECRET_USERNAME   #创建新的环境变量名称
       valueFrom:
        secretKeyRef:     #调用的key是什么
         name: mysecret       #变量的值来自于mysecret
         key: username       #username里面的值

2.创建使用secret的pod容器
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml 
pod/mypod created
3.连接
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash 
root@mypod:/data# echo $SECRET_USERNAME   #打印一下定义的变量
mahong
1.4 实战案例
1.创建数据库用户的密码secret
[root@kub-k8s-master test]# echo -n 'Mawenbao@123' | base64
TWF3ZW5iYW9AMTIz
[root@kub-k8s-master test]# cat secret.yml 
apiVersion: v1
kind: Secret
metadata:
 name: mysql-secret
type: Opaque
data:
 password: TWF3ZW5iYW9AMTIz
 
[root@kub-k8s-master test]# kubectl apply -f secret.yml

2.创建数据库并使用secret
[root@kub-k8s-master test]# cat mysql.yaml 
apiVersion: v1
kind: Pod
metadata:
 name: my-mysql
spec:
 containers:
 - name: mysql
   image: daocloud.io/library/mysql:5.7
   ports:
    - containerPort: 3306
   env:
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
       secretKeyRef:
        name: mysql-secret
        key: password
[root@kub-k8s-master test]# kubectl apply -f myslq.yaml
[root@kub-k8s-master test]# kubectl get pod -o wide 
NAME       READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
my-mysql   1/1     Running   0          2m47s   10.244.2.13   node2   <none>           <none>

测试:
[root@kub-k8s-master test]# mysql -uroot -p'Mawenbao@123' -h 10.244.2.13 -P3306

二.ConfigMap详解

 ConfigMap与 Secret 类似,用来存储配置文件的kubernetes资源对象,所有的配置内容都存储在etcd中。

与 Secret 的区别:

ConfigMap 保存的是不需要加密的、应用所需的配置信息。

ConfigMap 的用法几乎与 Secret 完全相同:可以使用 kubectl create configmap 从文件或者目录创建 ConfigMap,也可以直接编写 ConfigMap 对象的 YAML 文件。

2.1 创建ConfigMap的方式

创建ConfigMap的方式有4种:

命令行方式
方式1:通过直接在命令行中指定configmap参数创建,即--from-literal
方式2:通过指定文件创建,即将一个配置文件创建为一个ConfigMap,--from-file=<文件>
方式3:通过指定目录创建,即将一个目录下的所有配置文件创建为一个ConfigMap,--from-file=<目录>
配置文件方式
方式4:事先写好标准的configmap的yaml文件,然后kubectl create -f 创建

2.2 通过命令行参数创建

创建命令:

[root@kub-k8s-master prome]# kubectl create configmap test-configmap --from-literal=user=admin --from-literal=pass=1122334
configmap/test-configmap created

结果如下面的data内容所示:

[root@kub-k8s-master prome]# kubectl get configmap test-configmap -o yaml
apiVersion: v1
data:
  pass: "1122334"
  user: admin
kind: ConfigMap
metadata:
  creationTimestamp: "2019-10-21T07:48:15Z"
  name: test-configmap
  namespace: default
  resourceVersion: "187590"
  selfLink: /api/v1/namespaces/default/configmaps/test-configmap
  uid: 62a8a0d0-fab9-4159-86f4-a06aa213f4b1
2.3 通过指定文件创建

编辑文件server.conf内容如下:

[root@kub-k8s-master prome]# vim server.conf
server {
listen 80;
server_name localhost;
location / {
root /var/www/html;
index index.html index.htm;
}
}

 创建(可以有多个--from-file):

[root@kub-k8s-master prome]# kubectl create configmap test-config2 --from-file=server.conf
configmap/test-config2 created

结果如下面data内容所示:

[root@kub-k8s-master prome]# kubectl get configmap test-config2 -o yaml
apiVersion: v1
data:
  server.conf: |
    server {
    listen 80;
    server_name localhost;
    localtion / {
    root /var/www/html;
    index index.html index.htm;
    }
    }
kind: ConfigMap
metadata:
  creationTimestamp: "2023-10-21T08:01:43Z"
  name: test-config2
  namespace: default
  resourceVersion: "188765"
  selfLink: /api/v1/namespaces/default/configmaps/test-config2
  uid: 790fca12-3900-4bf3-a017-5af1070792e5

通过指定文件创建时,configmap会创建一个key/value对,key是文件名,value是文件内容。

2.4 指定目录创建

configs 目录下的config-1和config-2内容如下所示:

[root@kub-k8s-master prome]# mkdir config
[root@kub-k8s-master prome]# cd config/
[root@kub-k8s-master config]# vim config1
aaa
bbb
c=d
[root@kub-k8s-master config]# vim config2
eee
fff
h=k

 创建:

[root@kub-k8s-master config]# cd ..
[root@kub-k8s-master prome]# kubectl create configmap test-config3 --from-file=./config
configmap/test-config3 created

结果下面data内容所示:

[root@kub-k8s-master prome]# kubectl get configmap test-config3 -o yaml
apiVersion: v1
data:
  config1: |
    aaa
    bbb
    c=d
  config2: |
    eee
    fff
    h=k
kind: ConfigMap
metadata:
  creationTimestamp: "2023-10-21T08:20:42Z"
  name: test-config3
  namespace: default
  resourceVersion: "190420"
  selfLink: /api/v1/namespaces/default/configmaps/test-config3
  uid: 6e00fded-80a8-4297-aeb3-4c48795e6eb9

指定目录创建时,configmap内容中的各个文件会创建一个key/value对,key是文件名,value是文件内容。

2.5 通过yaml文件创建

yaml文件内容如下: 注意其中一个key的value有多行内容时的写法

[root@kub-k8s-master prome]# vim configmap.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-config4
  namespace: default
data:
  cache_host: memcached-gcxt
  cache_port: "11211"
  cache_prefix: gcxt
  my.cnf: |
   [mysqld]
   log-bin = mysql-bin
   haha = hehe

 创建:

[root@kub-k8s-master prome]# kubectl apply -f configmap.yaml 
configmap/test-config4 created

结果如下面data内容所示:

[root@kub-k8s-master prome]# kubectl get configmap test-config4 -o yaml
apiVersion: v1
data:
  cache_host: memcached-gcxt
  cache_port: "11211"
  cache_prefix: gcxt
  my.cnf: |
    [mysqld]
    log-bin = mysql-bin
    haha = hehe
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"cache_host":"memcached-gcxt","cache_port":"11211","cache_prefix":"gcxt","my.cnf":"[mysqld]\nlog-bin = mysql-bin\nhaha = hehe\n"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"test-config4","namespace":"default"}}
  creationTimestamp: "2023-10-21T08:30:24Z"
  name: test-config4
  namespace: default
  resourceVersion: "191270"
  selfLink: /api/v1/namespaces/default/configmaps/test-config4
  uid: 2a8cd6e7-db2c-4781-b005-e0b76d26394b

查看configmap的详细信息:

# kubectl describe configmap
2.6 使用ConfigMap

使用ConfigMap的方式,一种是通过环境变量的方式,直接传递pod,另一种是使用volume的方式挂载入到pod内

示例ConfigMap文件:

[root@kub-k8s-master prome]# vim config-map.yml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: config-map
  namespace: default
data:
  special.how: very
  special.type: charm  

创建  
[root@kub-k8s-master prome]# kubectl apply -f config-map.yml 
configmap/config-map created
2.6.1 通过变量使用

(1) 使用valueFrom、configMapKeyRef、name、key指定要用的key:

1.设置指定变量的方式
[root@kub-k8s-master prome]# vim testpod.yml
---
apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: daocloud.io/library/nginx
      env:   #专门在容器里面设置变量的关键字
        - name: SPECIAL_LEVEL_KEY   #这里的-name,是容器里设置的新变量的名字
          valueFrom:
            configMapKeyRef:
              name: config-map   #这里是来源于哪个configMap
              key: special.how      #configMap里的key
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: config-map
              key: special.type
  restartPolicy: Never

创建pod
[root@kub-k8s-master prome]# kubectl apply -f testpod.yml 
pod/dapi-test-pod created

测试:

[root@kub-k8s-master prome]# kubectl exec -it dapi-test-pod /bin/bash
root@dapi-test-pod:/# echo $SPECIAL_TYPE_KEY
charm

(2) 通过envFrom、configMapRef、name使得configmap中的所有key/value对儿  都自动变成环境变量:

[root@kub-k8s-master prome]# kubectl delete -f testpod.yml 
pod "dapi-test-pod" deleted
[root@kub-k8s-master prome]# cp testpod.yml testpod.yml.bak
[root@kub-k8s-master prome]# vim testpod.yml
---
apiVersion: v1
kind: Pod
metadata:
 name: dapi-test-pod
spec:
 containers:
   - name: test-container
     image: daocloud.io/library/nginx
     envFrom:
     - configMapRef:
         name: config-map
 restartPolicy: Never

 这样容器里的变量名称直接使用configMap里的key名:

[root@kub-k8s-master prome]# kubectl apply -f testpod.yml
pod/dapi-test-pod created.
[root@kub-k8s-master prome]# kubectl exec -it dapi-test-pod /bin/bash
root@dapi-test-pod:/# env
HOSTNAME=dapi-test-pod
NJS_VERSION=0.3.3
NGINX_VERSION=1.17.1
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PKG_RELEASE=1~stretch
KUBERNETES_PORT=tcp://10.96.0.1:443
PWD=/
special.how=very
HOME=/root
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
TERM=xterm
SHLVL=1
KUBERNETES_SERVICE_PORT=443
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
special.type=charm
KUBERNETES_SERVICE_HOST=10.96.0.1
_=/usr/bin/env
2.6.2 作为volume挂载使用

(1) 把1.4中test-config4所有key/value挂载进来:

[root@kub-k8s-master prome]# kubectl delete -f testpod.yml
pod "dapi-test-pod" deleted
[root@kub-k8s-master prome]# vim volupod.yml
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx-configmap
spec:
  containers:
  - name: nginx-configmap
    image: daocloud.io/library/nginx
    volumeMounts:
    - name: config-volume4
      mountPath: "/tmp/config4"
  volumes:
  - name: config-volume4
    configMap:
      name: test-config4
          
创建pod
[root@kub-k8s-master prome]# kubectl apply -f volupod.yml 
pod/nginx-configmap created

进入容器中/tmp/config4查看:

[root@kub-k8s-master prome]#  kubectl  exec -it nginx-configmap /bin/bash
root@nginx-configmap:/# ls /tmp/config4/
cache_host  cache_port	cache_prefix  my.cnf
root@nginx-configmap:/# cat /tmp/config4/cache_host 
memcached-gcxt
root@nginx-configmap:/#

可以看到,在config4文件夹下以每一个key为文件名,value为内容,创建了多个文件。

2.7 实战案例
创建configmap
[root@kub-k8s-master configmap]# vim configmap.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
 name: nginx-server-conf
 namespace: default
data:
 index.html: |
  Hello, cloud computing
  Hello, Mr. Wang

[root@kub-k8s-master configmap]# kubectl apply -f configmap.yaml

[root@kub-k8s-master configmap]# kubectl get configmap
NAME                DATA   AGE
nginx-server-conf   2      7s
[root@kub-k8s-master configmap]# kubectl get configmap nginx-server-conf -o yaml

使用configmap
[root@kub-k8s-master configmap]# vim pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
 name: test-webapp
spec:
 containers:
 - name: nginx-app
   image: daocloud.io/library/nginx
   ports:
    - containerPort: 80
   volumeMounts:
   - name: nginx-volume
     mountPath: "/usr/share/nginx/html"
 volumes:
 - name: nginx-volume
   configMap:
    name: nginx-server-conf
[root@kub-k8s-master configmap]# kubectl apply -f pod.yaml
[root@kub-k8s-master configmap]# kubectl get pod 
NAME          READY   STATUS    RESTARTS   AGE
test-webapp   1/1     Running   0          6s
[root@kub-k8s-master configmap]# kubectl exec -it test-webapp /bin/bash
root@test-webapp:/# cd /usr/share/nginx/html/
root@test-webapp:/usr/share/nginx/html# ls
index.html
root@test-webapp:/usr/share/nginx/html# cat index.html 
Hello, cloud computing
Hello, Mr. Wang

[root@kub-k8s-master configmap]# curl 10.244.2.25
Hello, cloud computing
Hello, Mr. Wang

三.Downward API

Downward API
用于在容器中获取 POD 的基本信息,kubernetes原生支持

Downward API提供了两种方式用于将 POD 的信息注入到容器内部:
1.环境变量:用于单个变量,可以将 POD 信息直接注入容器内部。
2.Volume挂载:将 POD 信息生成为文件,直接挂载到容器内部中去。

3.1 目前 Downward API 支持的字段

1. 使用 fieldRef 可以声明使用:
spec.nodeName - 宿主机名字
status.hostIP - 宿主机 IP
metadata.name - Pod 的名字
metadata.namespace - Pod 的 Namespace
status.podIP - Pod 的 IP
spec.serviceAccountName - Pod 的 Service Account 的名字
metadata.uid - Pod 的 UID
metadata.labels['<KEY>'] - 指定 <KEY> 的 Label 值
metadata.annotations['<KEY>'] - 指定 <KEY> 的 Annotation 值
metadata.labels - Pod 的所有 Label
metadata.annotations - Pod 的所有 Annotation

上面这个列表的内容,随着 Kubernetes 项目的发展肯定还会不断增加。所以这里列出来的信息仅供参考,在使用 Downward API 时,还是要记得去查阅一下官方文档。

# 所有基本信息可以使用下面的方式去查看(describe方式看不出来):
[root@kub-k8s-master configmap]# kubectl  get pod test-webapp -o yaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"test-webapp","namespace":"default"},"spec":{"containers":[{"image":"daocloud.io/library/nginx","name":"nginx-app","volumeMounts":[{"mountPath":"/usr/share/nginx/html","name":"nginx-volume"}]}],"volumes":[{"configMap":{"name":"nginx-server-conf"},"name":"nginx-volume"}]}}
  creationTimestamp: "2021-02-21T09:44:51Z"
  name: test-webapp
  namespace: default
  resourceVersion: "270687"
  selfLink: /api/v1/namespaces/default/pods/test-webapp
  uid: ed92d685-f800-464f-95dc-d6aa5f92fc9c
......
3.2 实战案例

使用fieldRef获取 POD 的基本信息,以环境变量的方式实现

[root@kub-k8s-master prome]# vim test-env-pod.yml
---
apiVersion: v1
kind: Pod
metadata:
    name: test-env-pod
    namespace: kube-system
spec:
    containers:
    - name: test-env-pod
      image: daocloud.io/library/nginx
      env:
      - name: POD_NAME   #第一个环境变量的名字
        valueFrom:      #使用valueFrom方式设置
          fieldRef:    #关联一个字段metadata.name
            fieldPath: metadata.name  #这个字段从当前运行的pod详细信息查看
      - name: POD_NAMESPACE
        valueFrom:
          fieldRef:
            fieldPath: metadata.namespace
      - name: POD_IP
        valueFrom:
          fieldRef:
            fieldPath: status.podIP

注意: POD 的 name 和 namespace 属于元数据,是在 POD 创建之前就已经定下来了的,所以使用 metadata 获取就可以了,但是对于 POD 的 IP 则不一样,因为POD IP 是不固定的,POD 重建了就变了,它属于状态数据,所以使用 status 去获取。 

 创建上面的 POD:

[root@kub-k8s-master prome]#  kubectl apply -f test-env-pod.yml
pod/test-env-pod created

 POD 创建成功后,查看:

[root@kub-k8s-master prome]# kubectl exec -it test-env-pod /bin/bash -n kube-system
root@test-env-pod:/# env | grep POD
POD_NAME=test-env-pod
POD_NAMESPACE=kube-system
POD_IP=10.244.1.35
root@test-env-pod:/#

Volume挂载

通过Downward API将 POD 的 Label、等信息通过 Volume 以文件的形式挂载到容器的某个文件中去,然后在容器中打印出该文件的值来验证。

[root@kub-k8s-master prome]# vim test-volume-pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
   name: test-volume-pod
   namespace: kube-system
   labels:
       k8s-app: test-volume
       node-env: test
spec:
   containers:
   - name: test-volume-pod-container
     image: daocloud.io/library/nginx
     volumeMounts:
     - name: podinfo
       mountPath: /etc/podinfo
   volumes:
   - name: podinfo
     downwardAPI:
       items:
       - path: "labels"
         fieldRef:
           fieldPath: metadata.labels

创建上面的 POD :

[root@kub-k8s-master prome]# kubectl apply -f test-volume-pod.yaml pod/test-volume-pod created
[root@kub-k8s-master prome]# kubectl get pod -n kube-system
[root@k8s-master prome]# kubectl exec -it test-volume-pod /bin/bash -n kube-system

Secret、ConfigMap,以及 Downward API 这三种 Projected Volume 定义的信息,大多还可以通过环境变量的方式出现在容器里。但是,通过环境变量获取这些信息的方式,不具备自动更新的能力。一般情况下,建议使用 Volume 文件的方式获取这些信息。 

四.ServiceAccount详解

官方文档地址:Configure Service Accounts for Pods | Kubernetes

k8s中提供了良好的多租户认证管理机制,如RBAC、ServiceAccount还有各种Policy等。 

什么是 Service Account ?

Pod里的进程也可以与 apiserver 联系。 当它们在联系 apiserver 的时候,它们就会被认证为一个特定的 Service Account。

使用场景:

  Service Account它并不是给kubernetes集群的用户使用的,而是给pod里面的进程使用的,它为pod提供必要的身份认证。----专门为pod里面的进程和apiserver通信提供认证的。

Service account与User account区别:

1. User account是为人设计的,而service account则是为Pod中的进程调用Kubernetes API或其他外部服务而设计的

2. User account是跨namespace的,而service account则是仅局限它所在的namespace; ​ 3. 每个namespace都会自动创建一个default service account     ​

4. Token controller检测service account的创建,并为它们创建secret

4.1 Service Account应用示例

Service Account(服务账号)示例

因为平时系统会使用默认service account,我们不需要自己创建,感觉不到service account的存在,本实验是使用自己手动创建的service account

1、创建serviceaccount
[root@kub-k8s-master ~]# kubectl create serviceaccount mysa
serviceaccount/mysa created
# yaml 方法创建
[root@kub-k8s-master ~]# vim mysa.yml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: mysa
  namespace: default

2、查看mysa
[root@kub-k8s-master ~]# kubectl describe sa mysa
Name:                mysa
Namespace:           default
Labels:              <none>
Annotations:         <none>  
Image pull secrets:  <none>
Mountable secrets:   mysa-token-cknwf
Tokens:              mysa-token-cknwf
Events:              <none>
3、查看mysa自动创建的secret
[root@kub-k8s-master ~]# kubectl  get secret
NAME                  TYPE                                  DATA   AGE
db-user-pass          Opaque                                2      11h
default-token-6svwp   kubernetes.io/service-account-token   3      4d23h
mysa-token-cknwf      kubernetes.io/service-account-token   3      76s
mysecret              Opaque                                2      11h
mysecret-01           Opaque                                2      6h58m
pass                  Opaque                                1      7h6m
user                  Opaque                                1      7h7m

4、创建角色和绑定
[root@kub-k8s-master ~]# vim role.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: mysa-role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: mysa-binding
  namespace: default
subjects:
- kind: ServiceAccount
  name: mysa
  namespace: default
roleRef:
  kind: Role
  name: mysa-role
  apiGroup: rbac.authorization.k8s.io
5、使用mysa的sa资源配置pod
[root@kub-k8s-master ~]# cd prome/
[root@kub-k8s-master prome]# vim mysa-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mysa-pod
spec:
  serviceAccountName: mysa
  containers:
  - name: app
    image: 10.36.192.206:8088/newrain857/kubectl
    command: ["tail","-f","/dev/null"]
 
6、导入
[root@kub-k8s-master prome]# kubectl apply -f .
pod/mysa-pod created
role.rbac.authorization.k8s.io/mysa-role created
rolebinding.rbac.authorization.k8s.io/mysa-binding created
serviceaccount/mysa created
7、查看
[root@kub-k8s-master prome]# kubectl get pod mysa-pod -o yaml
8、测试
[root@kube-master sa]# kubectl exec -it mysa-pod /bin/sh
/ # kubectl get pod
NAME             READY   STATUS    RESTARTS      AGE
nginx            1/1     Running   1 (50m ago)   17h
mysa-pod   1/1     Running   0             9m5s
/ # kubectl delete pod nginx
Error from server (Forbidden): pods "nginx" is forbidden: User "system:serviceaccount:default:pod-reader" cannot delete resource "pods" in API group "" in the namespace "default"

# 可以看到,我们已经成功限制了pod对资源的访问

五.RBAC 详解(基于角色的访问控制)

在Kubernetes中,授权有ABAC(基于属性的访问控制)、RBAC(基于角色的访问控制)、Webhook、Node、AlwaysDeny(一直拒绝)和AlwaysAllow(一直允许)这6种模式。

RBAC基于角色的访问控制--全拼Role-Based Access Control----做权限控制的,顾名思义就是通过给角色赋予相应的权限,从而使得该角色具有访问相关资源的权限。

k8s里面有两种用户,一种是User,一种就是service account(服务使用的账号)。
User account是为人设计的属于用户账户(个人使用的账号),此外User Account是跨Namespace的,而ServiceAccount则是仅局限它所在的Namespace。

在RABC API中,通过如下的步骤进行授权:
1)定义角色:在定义角色时会指定此角色对于资源的访问控制的规则;
2)绑定角色:将主体与角色进行绑定,对用户进行访问授权。

在K8s中这些资源分属于两个级别,名称空间(role/rolebinding)和集群级别(clusterrole/clusterrolebinding)这两个都是标准的K8s资源,可以直接定义。

Role与ClusterRole
 Role普通角色:一个Role对象只能用于授予对某一单一命名空间中资源的访问权限,普通角色只是在当前的名称空间生效。
 ClusterRole集群角色:整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现,可以访问整个集群资源。
 简介
role/ClusterRole:
    1、允许的操作,如get,list,update,create,delete等权限
    2、允许操作的对象,如pod,svc等资源

rolebinding:将哪个用户绑定到哪个role上
clusterrolebinding:绑定到集群角色上
   如果使用clusterrolebinding绑定到clusterrole上,表示绑定的用户拥有所有namespace的权限
   
 #这里面有哪些重要的东西:role,clusterrole,binding,账号。 

5.1 创建k8s账号与RBAC授权使用
创建账号
1、创建私钥
[root@kub-k8s-master ~]# (umask 077; openssl genrsa -out soso.key 2048)
Generating RSA private key, 2048 bit long modulus
...............................+++
..........................+++
e is 65537 (0x10001)

用此私钥创建一个csr(证书签名请求)文件
[root@kub-k8s-master ~]# openssl  req -new -key soso.key -out soso.csr -subj  "/CN=soso" # 这个地方是用户名

拿着私钥和请求文件生成证书
[root@kub-k8s-master ~]# openssl x509 -req -in soso.csr -CA  /etc/kubernetes/pki/ca.crt  -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out soso.crt -days 365
Signature ok
subject=/CN=soso
Getting CA Private Key

生成账号
[root@kub-k8s-master ~]# kubectl config set-credentials soso --client-certificate=soso.crt --client-key=soso.key --embed-certs=true
User "soso" set.

3、设置上下文环境--指的是创建这个账号的环境在当前名称空间中
[root@kub-k8s-master ~]# kubectl config set-context soso@kubernetes --cluster=kubernetes --user=soso
Context "soso@kubernetes" created.
查看当前的工作上下文
[root@kub-k8s-master ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.96.10:6443
....
4、切换用户(切换上下文)
[root@kub-k8s-master ~]# kubectl  config use-context soso@kubernetes
Switched to context "soso@kubernetes".
验证是否已经切换到了新的上下文
[root@kub-k8s-master ~]# kubectl config current-context
soso@kubernetes
5.测试(还未赋予权限)
[root@kub-k8s-master ~]# kubectl  get pod
Error from server (Forbidden): pods is forbidden: User "soso" cannot list resource "pods" in API group "" in the namespace "default"

创建一个角色(role)---设置权限
1.切回管理帐号先
[root@kub-k8s-master ~]# kubectl  config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".

创建角色(命令):
[root@kub-k8s-master ~]# kubectl  create role  role-reader  --verb=get,list,watch --resource=pod,svc
role.rbac.authorization.k8s.io/role-reader created
--verb: 相当于是权限
--resource:给什么资源使用

yaml文件方式:
[root@kub-k8s-master ~]# vim role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
 name: role-reader
rules: #定义规则
 - apiGroups: [""]  #表示当前pod使用核心的APIserver组,默认用""表示就可以
   resources: ["pods","svc"]
   verbs: ["get", "list", "watch", "create", "update", "delete"] #["*"]表示所有权限

[root@kub-k8s-master ~]# kubectl apply -f role.yaml 
role.rbac.authorization.k8s.io/role-reader created

[root@kub-k8s-master ~]# kubectl get roles
NAME          AGE
role-reader   30s

[root@kub-k8s-master ~]# kubectl describe role role-reader
Name:         role-reader
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"rbac.authorization.k8s.io/v1beta1","kind":"Role","metadata":{"annotations":{},"name":"role-reader","namespace":"default"},"...
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get list watch create update delete]
  svc        []                 []              [get list watch create update delete]

2.绑定用户soso(上面创建的用户),绑定用户到role-reader
[root@kub-k8s-master ~]# kubectl  create  rolebinding myrole-binding  --role=role-reader  --user=soso
rolebinding.rbac.authorization.k8s.io/myrole-binding created

yaml文件方式:
[root@k8s-master ~]# vim role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
 name: myrolebind
subjects:  #定义对那个主体进行操作,有三种Subjects:Service Account、User Account、Groups
- kind: User
  name: soso
  apiGroup: rbac.authorization.k8s.io
roleRef:  #定义使用哪个角色
  kind: Role
  name: role-reader
  apiGroup: rbac.authorization.k8s.io

[root@k8s-master ~]# kubectl apply -f role-binding.yaml 
rolebinding.rbac.authorization.k8s.io/myrolebind created

[root@k8s-master ~]# kubectl get rolebinding 
NAME         AGE
myrolebind   25s

3.切换用户
[root@kub-k8s-master ~]# kubectl  config use-context soso@kubernetes
Switched to context "soso@kubernetes".

4.查看权限(只授权了default名称空间pod和svc的get,list,watch权限)
[root@kub-k8s-master ~]# kubectl  get pod
NAME                    READY   STATUS    RESTARTS   AGE
lifecycle-demo          1/1     Running   1          22h
mypod                   1/1     Running   0          8h
nginx-configmap         1/1     Running   0          4h29m
nginx-pod               1/1     Running   0          39m
[root@kub-k8s-master ~]#  kubectl  get pod -n kube-system  #无权访问kube-system
Error from server (Forbidden): pods is forbidden: User "soso" cannot list resource "pods" in API group "" in the namespace "kube-system"

[root@kub-k8s-master ~]# kubectl  delete pod nginx-pod   #无权限删除
Error from server (Forbidden): pods "nginx-pod" is forbidden: User "soso" cannot delete resource "pods" in API group "" in the namespace "default"

5.切换用户
[root@kub-k8s-master ~]# kubectl  config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".



实验二,绑定用户到集群角色

6.删除soso账号之前绑定的rolebinding
[root@kub-k8s-master ~]# kubectl  delete rolebinding myrolebind
rolebinding.rbac.authorization.k8s.io "myrolebind" deleted

7.创建clusterrole #可以访问全部的namespace
[root@kub-k8s-master ~]# kubectl create clusterrole myclusterrole --verb=get,list,watch --resource=pod,svc
clusterrole.rbac.authorization.k8s.io/myclusterrole created

yaml文件方式:
[root@kub-k8s-master ~]# vim clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: myclusterrole
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch
[root@kub-k8s-master ~]# kubectl apply -f clusterrole.yaml
[root@kub-k8s-master ~]# kubectl get clusterrole

8.绑定集群角色到用户soso
[root@kub-k8s-master ~]# kubectl  create clusterrolebinding my-cluster-rolebinding   --clusterrole=myclusterrole --user=soso
clusterrolebinding.rbac.authorization.k8s.io/my-cluster-rolebinding created

yaml文件方式:
[root@kub-k8s-master ~]# vim clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: my-cluster-rolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: myclusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: soso
[root@kub-k8s-master ~]# kubectl apply -f clusterrolebinding.yaml
[root@kub-k8s-master ~]# kubectl get clusterrolebinding

9.切换账号
[root@kub-k8s-master ~]# kubectl  config use-context soso@kubernetes
Switched to context "soso@kubernetes".

10.查看权限 查看kube-system空间的pod
[root@kub-k8s-master ~]# kubectl  get pod -n kube-system
NAME                                     READY   STATUS    RESTARTS   AGE
coredns-5644d7b6d9-sm8hs                 1/1     Running   0          5d
coredns-5644d7b6d9-vddll                 1/1     Running   0          5d
etcd-kub-k8s-master                      1/1     Running   0          5d
... 

注意:11.切换为管理员用户
[root@kub-k8s-master ~]# kubectl  config use-context kubernetes-admin@kubernetes
5.2 设置上下文和账户切换

设置工作上下文(前提得有用户)

[root@kub-k8s-master ~]# kubectl  config   set-context  soso@kubernetes --cluster=kubernetes --user=soso
Context "soso@kubernetes" created.

查看当前的工作上下文

[root@kub-k8s-master ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
....

切换上下文(切换用户)

[root@kub-k8s-master ~]# kubectl config use-context soso@kubernetes
Switched to context "soso@kubernetes".

切换为管理员用户

[root@kub-k8s-master prome]# kubectl  config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".

查看某个资源类型是由哪个apiserver版本提供

[root@kub-k8s-master ~]# kubectl explain ClusterRole
  • 22
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果在Kubernetes集群中的某个节点上使用 `nc` 命令探测 `kube-dns` 的 `svcIP` 不通,但其他 `svc` 的 `IP` 可以通,可能是以下几个原因之一: 1. DNS Pod未运行或者不可用:`kube-dns` 是 Kubernetes 集群中负责 DNS 解析的组件。如果 `kube-dns` 的 Pod 未运行或者不可用,那么 `nc` 命令探测 `svcIP` 就会失败。你可以通过运行 `kubectl get pods -n kube-system` 命令来检查 `kube-dns` 的 Pod 状态,确保它们处于运行中且正常工作。 2. 节点网络配置问题:如果其他 `svc` 的 `IP` 可以通,但 `kube-dns` 的 `svcIP` 不通,可能是节点网络配置问题导致的。你可以检查该节点的网络配置,确保它可以与其他节点正常通信,并且没有任何防火墙规则或网络隔离策略阻止了与 `kube-dns` 的通信。 3. DNS服务设置错误:检查 Kubernetes 集群的 DNS 配置是否正确。你可以通过运行 `kubectl get services -n kube-system` 命令来获取 `kube-dns` 的服务信息,并确保 `kube-dns` 的服务正常运行并且暴露了正确的 `ClusterIP`。 4. DNS解析配置问题:检查节点的 DNS 解析配置是否正确。你可以尝试在该节点上手动解析 `kube-dns` 的 `svcIP`,并确保返回的结果与预期一致。你还可以检查节点上的 `/etc/resolv.conf` 文件,确保 DNS 配置正确并且指向了正确的 DNS 服务器。 如果以上方法仍然不能解决问题,建议你进一步检查节点和集群的网络配置以及 DNS 服务设置,以找到问题的具体原因。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值