kubernetes的学习

Posted weixin_45747080

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kubernetes的学习相关的知识,希望对你有一定的参考价值。

kubernetes的学习

本篇学习笔记总结自https://k8s.easydoc.net/,https://www.bilibili.com/video/BV1Tg411P7EB/

安装k8s集群

主节点需要的组件

  • docker(也可以是其他容器运行时)
  • kubectl 集群命令行交互工具
  • kubeadm 集群初始化工具

工作节点需要的组件

  • docker(也可以是其他容器运行时)
  • kubelet 管理 Pod 和容器,确保他们健康稳定运行。
  • kube-proxy 网络代理,负责网络相关的工作

部署应用到集群

使用pod

快速创建

--image=镜像地址

kubectl run <pod_name> --image==<image_url>

通过yaml文件创建单个pod

apiVersion: v1
kind: Pod
metadata:
	# pod名称
  name: test-k8s
spec:
  # 定义容器,可以多个
  containers:
    - name: test-k8s # 容器名字
      image: ccr.ccs.tencentyun.com/k8s-tutorial/test-k8s:v1 # 镜像

然后

kubectl apply -f <file_path.<yaml>>

通过yaml文件创建多个pod(deployment)

apiVersion: apps/v1
kind: Deployment
metadata:
  # 部署名字
  name: test-k8s
spec:
  replicas: 5
  # 用来查找关联的 Pod,所有标签都匹配才行
  selector:
    matchLabels:
      app: test-k8s
  # 定义 Pod 相关数据
  template:
    metadata:
      labels:
        app: test-k8s
    spec:
      # 定义容器,可以多个
      containers:
        - name: test-k8s # 容器名字
          image: ccr.ccs.tencentyun.com/k8s-tutorial/test-k8s:v1 # 镜像

然后

kubectl apply -f <file_path.<yaml>>

称之为development(部署),并且可以使用

kubectl get deployment

查询当前的部署情况

Tips

运行单个pod的yaml文件的kind为Pod,运行多个pod的yaml文件的kind为Deployment

进入pod的bash

kubectl exec -it <pod_name> -- bash

资源类型

常见的资源类型有

类型名称描述简写
podpo
deploymentdeploy
servicesvc
statefulsetsts
storage classsc
presistent volumepv
presistent volume claimpvc
config mapcm
sercet
name spacens

可以使用如下命令查看所有资源,资源名称及其简写

kubectl api-resources 

命令

apply

运行资源

kubectl apply [-f] <file_path>
										# -f:读取文件,然后运行

示例1,启用service资源:

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: test-k8s

...

运行:

kubectl apply -f service.yaml  # 读取该文件,然后运行资源

示例2:启动pod资源:

pod.yaml

apiVersion: v1
kind: Pod
metadata:
	# pod名称
  name: test-k8s

...

运行:

kubectl apply -f pod.yaml 

同理,还可以运行更多资源,如deployment、statefulset等,具体资源类型由文件的kind决定。

get

可以列出该类型的所有资源

kubectl get [资源类型] [-o wide|name|yaml|json]
											# all:列出所有资源,包括pod、deployment、service等
											# -o wide:详细信息
											# -o name:仅输出资源名称
											# -o yaml:YAML格式化输出
											# -o json:JSON格式化输出

示例:

kubectl get pod						# 列出所有pod
kubectl get pod	-o wide		# 以详细的方式列出所有pod

describe

查看资源的详细描述

kubectl describe [资源类型] <name>		# 第一种写法:资源类型(如pod、svc)+空格+具体名称
kubectl describe [资源类型]/<name> 		# 第二种写法:资源类型+/+具体名称
kubectl describe [资源类型]						# 第三种写法:资源类型,不加具体名称。查看所有该资源的详细描述

示例:

kubectl describe pod test-pod
kubectl describe pod/test-pod
kubectl describe pod

logs

查看资源的日志

kubectl logs [资源类型]/<name>	[-f] [-tail 100]			# 只能这种写法
																		# -f:循环读取,即可以读取不断改变的log
																		# -tail:读取最尾部xx行

示例:

kubectl logs pod/test-k8s

delete

删除资源

kubectl delete [资源类型] <name>
kubectl delete [资源类型]/<name>

示例:

kubectl delete pod/test-k8s

rollout

查看资源的变更历史history

kubectl rollout history [资源类型] <name>
kubectl rollout history [资源类型]/<name>

重新部署restart(仅适用于deployment)

kubectl rollout restart deployment/<name>

回退到上一版本undo

kubectl rollout undo deployment/<name>

回退到指定版本

kubectl rollout undo deployment/<name> --to-revision=2

port-forward

将资源转发到本地

kubectl port-forward [资源类型] <name> [local_port]:[remote_port]
kubectl port-forward [资源类型]/<name> [local_port]:[remote_port]

示例:

将资源的8090的端口转发到本地的8080

kubectl port-forward svc/test-k8s 8080:8090

其他命令

# 命令修改镜像,--record 表示把这个命令记录到操作历史中
kubectl set image deployment test-k8s test-k8s=ccr.ccs.tencentyun.com/k8s-tutorial/test-k8s:v2-with-error --record
# 暂停运行,暂停后,对 deployment 的修改不会立刻生效,恢复后才应用设置
kubectl rollout pause deployment test-k8s
# 恢复
kubectl rollout resume deployment test-k8s
# 重启
kubectl rollout restart deployment test-k8s
# 删除全部资源
kubectl delete all --all

service

特性

  • Service 通过 label 关联对应的 Pod
  • Servcie 生命周期不跟 Pod 绑定,不会因为 Pod 重创改变 IP
  • 提供了负载均衡功能,自动转发流量到不同 Pod
  • 可对集群外部提供访问端口
  • 集群内部可通过服务名字访问

Tips

service一共有四种type:

ClusterIP

默认的,仅在集群内可用

NodePort

暴露端口到节点,提供了集群外部访问的入口
端口范围固定 30000 ~ 32767

LoadBalancer

需要负载均衡器(通常都需要云服务商提供,裸机可以安装 METALLB 测试)
会额外生成一个 IP 对外服务
K8S 支持的负载均衡器:负载均衡器

Headless

适合数据库
clusterIp 设置为 None 就变成 Headless 了,不会再分配 IP

示例

service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: test-k8s
spec:
  selector:
    app: test-k8s
  # 默认 ClusterIP 集群内可访问,NodePort 节点可访问,LoadBalancer 负载均衡模式(需要负载均衡器才可用)
  type: ClusterIP
  ports:
    - port: 8080        # 本 Service 的端口
      targetPort: 8080  # 容器端口
#      nodePort: 31000   # 节点端口,范围固定 30000 ~ 32767

运行:

kubectl apply -f <service_path>

statefulset

StatefulSet 是用来管理有状态的应用,例如数据库。StatefulSet 会固定每个 Pod 的名字

特性

  • Service 的 ClusterIP 是空的,Pod 名字也是固定的。
  • Pod 创建和销毁是有序的,创建是顺序的,销毁是逆序的。
  • Pod 重建不会改变名字,除了IP,所以不要用IP直连

访问时,如果直接使用 Service 名字连接,会随机转发请求
要连接指定 Pod,可以这样pod-name.service-name

示例

mongo.yaml

# StatefulSet: mongodb
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
spec:
  replicas: 3
  serviceName: mongodb
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
        - name: mongo
          image: mongo:4.4
          # IfNotPresent 仅本地没有镜像时才远程拉,Always 永远都是从远程拉,Never 永远只用本地镜像,本地没有则报错
          imagePullPolicy: IfNotPresent
---

# Service: mongodb
apiVersion: v1
kind: Service
metadata:
  name: mongodb
spec:
  selector:
    app: mongodb
  type: ClusterIP
  # HeadLess
  clusterIP: None
  ports:
    - port: 27017
      targetPort: 27017

运行:

kubectl apply -f <file_path>

pod、deployment、service、statefulset四者的关系

这四者在yaml文件中通过指定不同的kind来区分,pod是deployment和statefulset运行的最小单元,deployment和statefulset可以通过指定spec.replicas来扩展多个pod,deployment启动的pod默认的名称为deploy名称+无序字符,而statefulset启动的pod的默认名称为statefulset名称+有序数字,如

$ kubectl get pod
NAME                        READY   STATUS    RESTARTS      AGE
mongodb-0                   1/1     Running   1 (20h ago)   3d17h
test-k8s-75bd6fbdbc-72rxc   1/1     Running   1 (20h ago)   3d17h
test-k8s-75bd6fbdbc-ns5h2   1/1     Running   1 (20h ago)   3d17h

启动service并不会创建pod,只是service会通过label来关联pod或者deploy或者statefulset,可以随之进行端口转发,供外部访问。由于service是通过label关联pod的,所以pod销毁service也不会销毁的。

数据持久化

k8s集群并不会为你处理数据的存储,我们可以为数据库挂载一个磁盘来确保数据的持久化。可以选择云存储、本地磁盘、NFS。

  • 本地磁盘:可以挂载某个节点上的目录,但是这需要限定 pod 在这个节点上运行
  • 云存储:不限定节点,不受集群影响,安全稳定;需要云服务商提供,裸机集群是没有的。
  • NFS:不限定节点,不受集群影响

hostPath

把节点上的一个目录挂载到 Pod,但是已经不推荐使用了,文档
配置方式简单,需要手动指定 Pod 跑在某个固定的节点。
仅供单节点测试使用;不适用于多节点集群。
minikube 提供了 hostPath 存储,文档

将容器卷的挂载路径(volumeMounts)指向节点的卷路径(volumes

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
spec:
  replicas: 1
  serviceName: mongodb
  selector:
    matchLabels:
      app: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
        - name: mongo
          image: mongo:4.4
          # IfNotPresent 仅本地没有镜像时才远程拉,Always 永远都是从远程拉,Never 永远只用本地镜像,本地没有则报错
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - mountPath: /data/db # 容器里面的挂载路径
              name: mongo-data    # 卷名字,必须跟下面定义的名字一致
      volumes:
        - name: mongo-data              # 卷名字
          hostPath:
            path: /data/mongo-data      # 节点上的路径
            type: DirectoryOrCreate     # 指向一个目录,不存在时自动创建
#        - name: mongo-data
#            persistentVolumeClaim:
#              claimName: mongodata
---
apiVersion: v1
kind: Service
metadata:
  name: mongodb
spec:
  selector:
    app: mongodb
  type: ClusterIP
  # HeadLess
  clusterIP: None
  ports:
    - port: 27017
      protocol: TCP
      targetPort: 27017

ConfigMap

yaml文件的kind是ConfigMap官方文档

示例

configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  # config-map的名称
  name: mongo-config

data:
  # key-value
  mongo-address: mongodb-0.mongodb:27017

运行:

kubectl apply -f configmap.yaml

通过get查看并且输出为yaml格式

kubectl get cm mongo-config -o yaml

接下来就可以在其他地方被读取了,这里以一个App的环境变量为例:

app.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  # 部署名字
  name: test-k8s
spec:
  replicas: 2
  # 用来查找关联的 Pod,所有标签都匹配才行
  selector:
    matchLabels:
      app: test-k8s
  # 定义 Pod 相关数据
  template:
    metadata:
      labels:
        app: test-k8s
    spec:
      # 等待 mongodb 起来后才启动
      initContainers:
      - name: wait-mongo
        image: busybox:1.28
        command: ['sh', '-c', "until nslookup mongodb; do echo waiting for mongo; sleep 2; done"]
      # 定义容器,可以多个
      containers:
      - name: test-k8s # 容器名字
        image: ccr.ccs.tencentyun.com/k8s-tutorial/test-k8s:v4-configmap # 镜像
        env:
          - name: MONGO_USERNAME
            valueFrom:
              secretKeyRef:
                name: mongo-secret
                key: mongo-username
          - name: MONGO_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mongo-secret
                key: mongo-password
          - name: MONGO_ADDRESS
            valueFrom:
              # 从config map资源中取
              configMapKeyRef:
                # 资源名称
                name: mongo-config
                # 取资源中对应的key的value
                key: mongo-address
---
apiVersion: v1
kind: Service
metadata:
  name: test-k8s
spec:
  selector:
    app: test-k8s
  # 默认 ClusterIp 集群内可访问,NodePort 节点可访问,LoadBalancer 负载均衡模式(需要负载均衡器才可用)
  type: NodePort
  ports:
    - nodePort: 31000   # 节点端口,范围固定 30000 ~ 32767
      port: 8080        # 本 Service 的端口
      targetPort: 8080  # 容器端口

可以看到env[2].name的valueFrom中是configMapKeyRef,则代表使用ConfigMap资源中取,并且指定ConfigMap资源的名称和key,即可以读取到内容了。

这里的env:MONGO_ADDRESS是从名叫mongo-config的ConfigMap资源中读取key为mongo-address对应的value,即mongodb-0.mongodb:27017

Secret

yaml文件的kind是Secret官方文档

示例

secret.yaml

apiVersion: v1
kind: Secret
metadata:
  # secret的名称
  name: mongo-secret
# 默认的type是Opaque
type: Opaque

data:
  # key-value
  # 需要进行base64加密处理
  mongo-username: bW9uZ291c2Vy
  mongo-password: bW9uZ29wYXNz

运行

kubectl apply -f secret.yaml

以yaml文件格式查看

kubectl get secret mongo-secret -o yaml

接下来就可以被其他地方读取了,这里mongo的statefulset为例

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mongodb
  serviceName: mongodb
  template:
    metadata:
      labels:
        app: mongodb
    spec:
      containers:
        - name: mongo
          image: mongo:4.4
          # IfNotPresent:仅本地没有镜像时才远程拉,Always:永远都是从远程拉,Never:永远只用本地镜像,本地没有则报错
          imagePullPolicy: IfNotPresent
          # 该container的环境变量列表
          env:  
          # 环境变量名称
          - name: MONGO_INITDB_ROOT_USERNAME
            valueFrom:
              # 'secretKeyRef'表示从secret资源中取
              secretKeyRef:
                # 指定secret的名称
                name: mongo-secret
                # 取secret中的key对应的value
                key: mongo-username                                          
          - name: MONGO_INITDB_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mongo-secret
                key: mongo-password
---
apiVersion: v1
kind: Service
metadata:
  name: mongodb
spec:
  selector:
    app: mongodb
  type: ClusterIP
  # HeadLess
  clusterIP: None
  ports:
    - port: 27017
      protocol: TCP
      targetPort: 27017

可以看到env[0].name的valueFrom中是secretKeyRef,则代表使用Secret资源中取,并且指定Secret资源的名称和key,即可以读取到内容了。

这里的env:MONGO_INITDB_ROOT_USERNAME是从名叫mongo-secret的ConfigMap资源中读取key为mongo-username对应的value,即bW9uZ291c2Vy,env:MONGO_INITDB_ROOT_PASSWORD同理。

可以看到,configMap和secret读取的方式是差不多的。

Tips

如果type是Opaque的话,那么data需要进行base64处理

Helm

Helm类似 npm,pip,docker hub, 可以理解为是一个软件库,可以方便快速的为我们的集群安装一些第三方软件。
使用 Helm 我们可以非常方便的就搭建出来 MongoDB / mysql 副本集群,YAML 文件别人都给我们写好了,直接使用。官网应用中心

我们可以在应用中心搜索集群,然后添加源并且安装就可以快速创建集群了,不需要自己手动写配置文件,并且我们可以在安装集群的时候手动指定一些参数。

示例:安装mongodb

1、添加源

helm repo add bitnami https://charts.bitnami.com/bitnami

2、安装

# 默认安装
helm install first-mongo bitnami/mongodb	
# 指定参数安装
helm install my-mongo bitnami/mongodb --set architecture="replicaset",auth.rootPassword="mongopass"  

具体可以手动指定的参数可以在应用中心中查看

3、查看密码

kubectl get secret my-mongo-mongodb -o yaml
# 查看密码并且写入文件
kubectl get secret my-mongo-mongodb -o yaml > secret.yaml

4、查看

可以查看到通过helm,已经自动安装好了包含可以扩展的pod、service、statefulset的集群。

kubectl get all

5、测试

临时运行一个包含 mongo client 的 debian 系统

kubectl run mongodb-client --rm --tty -i --restart='Never' --image docker.io/bitnami/mongodb:4.4.10-debian-10-r20 --command -- bash

在client中利用url、username、password连接mongo server

mongo --host my-mongo-mongodb-0.my-mongo-mongodb-headless.default.svc.cluster.local:27017 -u root -p mongopass

6、转发集群端口到宿主机

此时可以通过宿主机的工具来尝试连接mongo server,如Navicat、DateGrip等。

kubectl port-forward svc/my-mongo-mongodb-headless 27018:27017

7、删除集群

helm delete first-mongo

namespace

列出所有命名空间

kubectl get ns

查看默认的命名空间

kubectl get all

查看指定的命名空间

kubectl get all -n <namespace>

示例

查看k8s系统的命名空间

kubectl get all -n kube-system

创建命名空间

每次部署或者查询时候都需要指定命名空间

kubectl create namespace testns

部署应用到指定命名空间

kubectl apply -f app.yml [-n|--namespace] <namespace>

然后查询

kubectl get pod [-n|--namespace] <namespace>

每次部署应用或者查询时候都需要指定命名空间

kubens

每次部署或者查询时候都需要指定命名空间有点麻烦,可以利用kubens快速切换命名空间,后续的命令就不需要再利用-n|--namespace指定命名空间了。

查看所有命名空间

高亮显示当前所位于的命名空间

kubens

切换到指定命名空间

kubens <namespace>

切换回上一命名空间

kubens -

kubectx

快速切换集群

Ingress

yaml文件的kind是Ingress官方文档,是一个作用类似于nginx的,能够提供对集群中的服务的外部访问进行管理的API对象

示例

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-example
spec:
  ingressClassName: nginx
  rules:
  - host: tools.fun
    http:
      paths:
      # 匹配'/easydoc'转发到service1
      - path: /easydoc
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 4200
      # 匹配'/svnbucket'转发到service2
      - path: /svnbucket
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 8080

其他

Service中type为ClusterIP和NodePort的区别

ClusterIP:通过集群内部的IP暴露服务,选择该值的时候服务只能在集群内部访问。是service默认的type。

NodePort:通过每个节点上的IP和静态端口暴露服务。NodePort服务会路由到自动创建的ClusterIP服务,通过请求 <节点 IP>:<节点端口>,你可以从集群的外部访问一个 NodePort 服务。

ConfigMap和Secret的区别

ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。

注意:

ConfigMap 并不提供保密或者加密功能。 如果你想存储的数据是机密的,请使用 Secret, 或者使用其他第三方工具来保证你的数据的私密性,而不是用 ConfigMap。

Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。

使用dashboard可视化管理

默认情况下不会部署 Dashboard。可以通过以下命令部署:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml

使用

kubectl proxy

输入网址:

http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

以上是关于kubernetes的学习的主要内容,如果未能解决你的问题,请参考以下文章

二进制安装kubernetes kubectl命令行工具使用详解

Kubernetes 设置图像缺少资源类型“部署”

Docker&Kubernetes ❀ Kubernetes集群Service资源配置清单

Docker&Kubernetes ❀ Kubernetes集群Service资源配置清单

云原生之kubernetes实战kubernetes集群的Service资源对象

kubernetes之计算机资源管理