k8s中常见的资源对象的使用

Deployment

 

基本特性:

       确保预期的pod副本数量

       无状态应用部署

       有状态应用部署

       确保所有的node运行同一个pod

       一次性任务和定时任务

 

与Pod之间的关系

       Pod是通过Controller实现应用的运维,例如伸缩,滚动升级。

       Pod和Controller之间通过label标签和selector选择器建立关系

 

应用场景

       部署无状态应,web服务,微服务

       管理Pod和ReplicaSet

       部署,滚动升级等功能

 

 示例:

root@deploy:/opt/k8s-data# cat deployment.yml                                                                                          
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  selector:
    matchLabels:
      app: web
  replicas: 2
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
        - name: tomcat
          image: tomcat
          imagePullPolicy: IfNotPresent
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: web-service
  name: web-service
  namespace: default
spec:
  type: NodePort
  ports:
  - name: nginx
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30001
  - name: tomcat
    port: 8080
    protocol: TCP
    targetPort: 8080
    nodePort: 30002
  selector:
    app: web

 

  验证访问

 

 

 

Deployment滚动升级

  Deployment每次创建的Pod数量是可以定制的。 Kubernetes提供了两个参数maxSurge和maxUnavailable来精细控制Pod的替换数量 。

  Deployment会在.spec.strategy.type==RollingUpdate时,采取滚动更新的方式更新Pods。

  指定maxUnavailable和maxSurge来控制滚动更新过程。

 

最大不可用

  .spec.strategy.rollingUpdate.maxUnavailable是一个可选字段,用来指定更新过程中不可用的Pod的个数上限。该值可以是绝对数字(例如,5),也可以是所需 Pods的百分比(例如,10%)。百分比值会转换成绝对数并去除小数部分。如果.spec.strategy.rollingUpdate.maxSurge为0,则此值不能为0。默认值为25%。

 

  maxUnavailable,此参数控制滚动更新过程中不可用的副本相占DESIRED的最大比例。maxUnavailable可以是具体的整数(比如3),也可以是百分百,向下取整。maxUnavailable默认值为25%。

  例如,DESIRED为10,那么可用的副本数至少要为10 - roundDown(10 * 25%)= 8,所以看到AVAILABLE是8。(则Deployment创建的pod副本数为4,升级过程中,旧的数量副本数为3,4-4*0.25)

 

  例如,当此值设置为30%时,滚动更新开始时会立即将旧ReplicaSet缩容到期望Pod个数的70%。新Pod准备就绪后,可以继续缩容旧有的ReplicaSet,然后对新的ReplicaSet扩容,确保在更新期间可用的Pods总数在任何时候都至少为所需的Pod个数的70%。

 

最大峰值

  .spec.strategy.rollingUpdate.maxSurge 是一个可选字段,用来指定可以创建的超出期望 Pod 个数的 Pod 数量。此值可以是绝对数(例如,5)或所需 Pods 的百分比(例如,10%)。如果 MaxUnavailable 为 0,则此值不能为 0。百分比值会通过向上取整转换为绝对数。此字段的默认值为 25%。

  maxSurge,此参数控制滚动更新过程中副本总数超DESIRE的上限。maxSurge可以是具体的整数(比如3),也可以是百分百,向上取整。maxSurge默认值为25%。例如, DESIRED为10, 那么副本总数的最大值为roundUp(10 + 10 * 25%) =13,所以看到CURRENT就是13。

  例如,当此值为30%时,启动滚动更新后,会立即对新的ReplicaSet扩容,同时保证新旧Pod的总数不超过所需 Pod 总数的 130%。一旦旧Pods被杀死,新的ReplicaSet可以进一步扩容,同时确保更新期间的任何时候运行中的Pods 总数最多为所需Pods总数的 130%。(例如:当前4个副本,最大峰值为25%,则副本pod数量最高不能超过5个,4+4*0.25)

 

滚动升级

kubectl set image deployment/nginx nginx=10.0.0.11:5000/lxh/nginx:v1 --record
# --record记录滚动升级的change-cause,能在rollout history中体现

 

验证:升级成功

kube# kubectl rollout status deployment web
deployment "web" successfully rolled out

 

  查看升级的历史:

root@master:~/.kube# kubectl rollout history deployment web 
deployment.apps/web 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         kubectl set image deployment/nginx nginx=10.0.0.11:5000/lxh/nginx:v1 --record=true

 

 

Deployment回滚

  undo默认还原至上一个版本

kubectl rollout undo deployment/nginx

  回滚可以在升级后进行版本回退

  

  使用--to-reversion=<版本号>,指定版本进行回滚

root@master:~/.kube# kubectl rollout undo deployment web --to-revision=3
deployment.apps/web rolled back

 

 

Deployment终止升级

kubectl rollout pause deployment web

 

 

Deployment恢复终止升级

kubectl rollout resume deployment web

 

 

SVC

 Kubernetes Service定义了这样一种抽象:一个Pod的逻辑分组,一种可以访问它们的策略 —— 通常称为微服务。这一组Pod能够被Service访问到,通常是通过Label Selector

 

  Service能够提供负载均衡的能力,但是在使用上有以下限制:

  只提供 4 层负载均衡能力,而没有 7 层功能,但有时可能需要更多的匹配规则来转发请求,这点上 4 层负载均衡是不支持的

 

Service存在意义

(1)防止Pod失联(服务)

(2)定义一组pod的访问策略(负载均衡)

 

       service类型

       --type参数:

       (1)clusterIP:集群内部使用

       (2)NodePort:对外访问应用

       (3)LoadBalance:对外访问应用,公有云

 

 

clusterIP

  用于pod之间互访访问,访问方式:直接访问service名称

  

  多端口service示例:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9376
    - name: https
      protocol: TCP
      port: 443
      targetPort: 9377

 

  查看后端pod节点:(type为clueterIP)

[root@master10 svc]# kubectl get endpoints
NAME     ENDPOINTS                                     AGE
svc-dp-nginx   10.100.222.185:80,10.100.72.45:80,10.100.72.46:80   4m28s

  验证service,pod内部之间访问:

 

NodePort

  默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号(默认:30000-32767)

 

  多端口创建svc

kubectl expose deployment nginx --type=NodePort --port=80,443 --target-port=80,443 --dry-run=client -o yaml > svc_multiport.yaml

cat svc_multiport.yaml

apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  ports:
  - nodePort: 32110
    name: port-1
    port: 80
    protocol: TCP
    targetPort: 80
  - nodePort: 32443
    name: port-2
    port: 443
    protocol: TCP
    targetPort: 443
  selector:
    app: nginx
  type: NodePort
status:
  loadBalancer: {}

 

手动命令expose创建svc

  先创建SVC,默认clusterIP模式

kubectl expose deployment nginx-deployment --port=8080 --target-port=80
#指定deployment,将nginx访问的80端口转发到8080

[root@master01 ~]# kubectl get svc  #查看SVC
NAME   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes         ClusterIP   10.96.0.1       <none>        443/TCP    14d
nginx-deployment   ClusterIP   10.100.139.198  <none>        8080/TCP   84s
访问验证
[root@master01 ~]# curl -I 10.100.139.198:8080  #成功访问
HTTP/1.1 200 OK
Server: nginx/1.19.5
Date: Sun, 13 Dec 2020 01:27:10 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 24 Nov 2020 13:02:03 GMT
Connection: keep-alive
ETag: "5fbd044b-264"
Accept-Ranges: bytes

[root@master01 ~]# ipvsadm -Ln	#查看LVS成功负载均衡,并做了rr轮询
TCP  10.200.139.198:8080 rr
  -> 10.100.1.17:80               Masq    1      0          0
  -> 10.100.1.18:80               Masq    1      0          1
  -> 10.100.2.2:80

 

 

  配置转发映射为NodePort模式,暴露SVC端口

[root@master01 ~]# kubectl edit svc nginx-deployment  #编辑SVC配置文件
spec:
  clusterIP: 10.100.139.198
  externalTrafficPolicy: Cluster
  ports:
  - nodePort: 30401
    port: 8080
    protocol: TCP
    targetPort: 80
  selector:
    run: nginx-deployment
  sessionAffinity: None
  type: NodePort				#将ClusterIP修改为NodePort

[root@master01 ~]# kubectl get svc   #验证,得到映射到本机的30401端口
NAME    TYPE   CLUSTER-IP   EXTERNAL-IP   PORT(S)       AGE
kubernetes    ClusterIP   10.100.0.1        <none>        443/TCP          14d
nginx-deployment   NodePort    10.100.139.198   <none>        8080:30401/TCP   7m24s

[root@master01 ~]# ss -lntup|grep 30401  #本地端口已被监听
tcp    LISTEN     0      128    [::]:30401              [::]:*                   users:(("kube-proxy",pid=3114,fd=11))

 

 

ConfigMap

       Configmap配置信息和镜像解耦,实现方式为将配置信息放到configmap对象中,然后再pod的中做为Volume挂载到pod中,从而实现导入配置的目的。

      

       使用场景:

       通过Configmap给pod定义全局环境变量

       通过Configmap给pod传递命令行参数,如mysql -u -p中的账户名密码可以通过Configmap传递。

       通过Configmap给pod中的容器服务提供配置文件,配置文件以挂载到容器的形式使用。

      

       作用:

       存储不加密数据到etcd,让Pod以变量或者Volume挂载到容器中。

与Secret的区别在于:Secret对数据加密,ConfigMap不对数据加密

 

       注意:

       Configmap需要在pod使用它之前创建。

       pod只能使用位于同一个namespace的Configmap、及Configmap不能跨namespace使用

       通常用于非安全加密的配置场景。

       Configmap通常是小于1MB的配置。

 

 

       使用场景:服务的配置文件

 

       Nginx配置文件

       1、创建config文件

       conf 与 conf2分别是key ,“|”管道符对应 value内容

root@deploy:~# mkdir config/
root@deploy:~# cd config/
root@deploy:~/config# vim config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
data:
  conf: |
    server {
       listen       8080;
       server_name  www.configtest.com;

       location / {
           root /usr/share/nginx/html/configtest;
           index index.html index.htm;           
       }
    }
  conf2: |
    server {
       listen       8081;
       server_name  www.configtest2.com;

       location / {
           root /usr/share/nginx/html/configtest2;
           index index.html index.htm;
       }
    }

root@deploy:~/config# kubectl apply -f config.yaml

 

 

       2、创建应用和svc

root@deploy:~/config# vim nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web
  name: web-deployment
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        - name: nginx-conf
          mountPath: "/etc/nginx/conf.d"
      - name: nginx-conf
        configMap:
          name: nginx-config
          items:
            - key: conf
              path: web.conf 
            - key: conf2
              path: web2.conf
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: web-svc
  name: web-svc
  namespace: default
spec:
  ports:
  - name: web1
    port: 80
    protocol: TCP
    targetPort: 8080
    nodePort: 30220
  - name: web2
    port: 81
    protocol: TCP
    targetPort: 8081
    nodePort: 30221
  selector:
    app: web
  type: NodePort

 

 

       查看创建的cofnigmap

 

       查看pods

 

       查看svc

 

  客户端访问测试:

 

 

  以Volume挂载到pod容器中

  创建pod yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: busybox
    image: busybox
    command: [ "/bin/sh","-c","cat /etc/config/redis.properties" ]
    volumeMounts:
    - name: config-volume
      mountPath: "/etc/config"
  volumes:
  - name: config-volume
    configMap:
      name: redis-config
  restartPolicy: Never

 

  验证:查看pod容器内日志输出

  以变量形式挂载到pod容器中

  创建ConfigMap yaml文件,声明两个变量special.level,special.type

apiVersion: v1
kind: ConfigMap
metadata:
  name: myconfig
  namespace: default
data:
  special.level: info
  special.type: hello

 

  查看创建的configmap,在DATA一列为对应的两个变量

 

  创建pod yaml,声明两个变量:LEVEL、TYPE,输出两个变量信息

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: busybox
    image: busybox
    command: [ "/bin/sh","-c","echo ${LEVEL} ${TYPE}" ]
    env:
      - name: LEVEL
        valueFrom:
          configMapKeyRef:
            name: myconfig
            key: special.level
      - name: TYPE
        valueFrom:
          configMapKeyRef:
            name: myconfig
            key: special.type
  restartPolicy: Never

 

  查看pod日志输出变量信息

 

 

Secret

       secret用来保存小片敏感数据的k8s资源,例如密码,token,OCP客户端配

置文件,Docker配置文件,私有sorce registry凭据或者秘钥。Secret对象可以与

pods分离独立定义,通过临时卷将敏感信息挂载给pods使用。这类数据当然也可以存放在Pod或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,并减少暴露的风险。

 

       在通过yaml文件创建secret时,可以设置data或stringData字段,data和stringData字段都是可选的,data字段中所有键值都必须是base64编码的字符串,如果不希望执行base64字符串的转换操作,也可以选择设置stringData字段,其中可以使用任何非加密的字符串作为其取值。

 

Secret类型

  (1)generic:键值对,对变量值base64加密,类型为Opaque。

  (2)docker-registry:用于访问registry仓库的凭据,类型kubernetes.io/dockerconfigjson。

  (3)tls:保存TLS公钥和私钥,类型为Opaque。

       (4)basic-auth:用于基本身份验证凭据

       (5)ssh-auth:用于SSH身份认证的凭据

       (6)token:启动引导令牌数据

       (7)service-account-token:ServiceAccount令牌

 

场景:generic

1、使用--from-literal=<key>=<value>标签提供Secret数据。

可以多次使用此标签,提供多个键值对。请注意,特殊字符(例如:$,\,*,= 和 !)由你的shell解释执行,而且需要转义。

kubectl create secret generic mysecret1 --from-literal=user=tom --from-literal=password1=redhat --from-literal=password2=redhat

 

  查看yaml配置

kubectl get secrets mysecret1 -o yaml

apiVersion: v1
data:
  password1: cmVkaGF0
  password2: cmVkaGF0
  user: dG9t
kind: Secret
metadata:
  creationTimestamp: "2022-06-25T06:04:14Z"
  name: mysecret1
  namespace: default
  resourceVersion: "84642"
  uid: 8eebe653-53f3-4834-a00a-dc9278c27bcc
type: Opaque

 

   base64 –d解密

echo -n dG9t|base64 -d
tom
echo -n cmVkaGF0|base64 -d
redhat

 

 

  2、使用指定文件创建secret

  (1)--from-file,指定文件进行创建secret,并以文件名作为secret的key。

一个 Secret 可以包含 Pod 访问数据库所需的用户凭证。例如,由用户名和密码组成的数据库连接字符串。可以在本地计算机上,将用户名存储在文件./username.txt中,将密码存储在文件./password.txt 中。

  echo -n 标志确保生成的文件在文本末尾不包含额外的换行符。 这一点很重要,因为当 kubectl 读取文件并将内容编码为 base64 字符串时,多余的换行符也会被编码。

echo -n 'admin' > ./username.txt
echo -n '1f2d1e2e67df' > ./password.txt
kubectl create secret generic db-user-pass \
  --from-file=./username.txt \
  --from-file=./password.txt

  

  查看yaml配置

  key则是文件名,所以使用文件名作为key应规范创建密码文件

kubectl get secrets db-user-pass -o yaml
apiVersion: v1
data:
  password.txt: MWYyZDFlMmU2N2Rm
  username.txt: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2022-06-25T07:02:47Z"
  name: db-user-pass
  namespace: default
  resourceVersion: "89570"
  uid: e8da86e3-5079-4443-b58c-480a0a085608
type: Opaque

 

  解码 Secret
  要查看创建的 Secret 的内容,运行以下命令:

kubectl get secret db-user-pass -o jsonpath='{.data}'

 

  输出

{"password":"MWYyZDFlMmU2N2Rm","username":"YWRtaW4="}

 

 

 (2)使用--from-env-file指定文件进行创建secret key和value

cat env.txt
username=admin
password=R0ot!z#$

kubectl create secret generic secretenv --from-env-file=env.txt

 

  查看yaml配置

kubectl get secrets secretenv -o yaml
apiVersion: v1
data:
  password: UjBvdCF6IyQ=
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2022-06-25T07:23:01Z"
  name: secretenv
  namespace: default
  resourceVersion: "91271"
  uid: 8be27660-c2d4-438a-b381-18e9582b9c4b
type: Opaque

 

  3、stringData非加密类型

       以使用任何非加密的字符串作为其取值

root@deploy:~/config# vim stringData.yaml
apiVersion: v1
stringData:
  user: "admin"
  password: "admin"
kind: Secret
metadata:
  name: user-pass
  namespace: default
type: Opaque

 

       查看stringData信息得到的是非加密的

 

场景:凭证

       作用:加密数据存在etcd里面,让Pod容器以挂载Volume方式进行访问

       示例:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4K
  password: MTIzNDU2Cg==

 

  1、以变量形式挂载到pod容器中

       pod声明用户名变量和密码变量:分别是SECRET_USERNAME,SECRET_PASSWORD

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: nginx
      image: nginx
      env:
        - name: SECRET_USERNAME
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: username
        - name: SECRET_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: password

 

验证:

       进入到容器内,输出变量得到base64解码内容

 

  创建数据库凭据

kubectl create secret generic mysecret --from-literal=username=root --from-literal=password=123456

cat secret_env.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels:
    name: mysql
spec:
  containers:
  - image: hub.c.163.com/library/mysql:latest
    imagePullPolicy: IfNotPresent
    name: mysql
    ports:
    - containerPort: 3306
      name: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
        # 原先通过value设置环境变量值
      valueFrom:
        secretKeyRef:
          name: mysecret
          key: password

 

  验证

  登录mysql,输入密码123456

  2、以Volume形式挂载到容器中

  (1)创建secret,nginx发布

kubectl create secret generic mysecret --from-literal="index.html"='hello K8s'

kubectl get secrets mysecret -o yaml
apiVersion: v1
data:
  index.html: aGVsbG8gSzhz
kind: Secret
metadata:
  creationTimestamp: "2022-06-25T08:01:31Z"
  name: mysecret
  namespace: default
  resourceVersion: "94519"
  uid: d97f7880-9301-46e2-9bbb-7cd979750d77
type: Opaque

 

  创建pod,以volume形式引用secret

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: foo
      mountPath: "/usr/share/nginx/html"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret

 

 

  验证:

 

posted @ 2022-08-04 15:47  PunchLinux  阅读(534)  评论(0)    收藏  举报