K8S 集群架构
master
主节点,控制平台,不需要很高性能,不跑任务,通常一个就行了,也可以开多个主节点来提高集群可用度worker
工作节点,可以是虚拟机或物理计算机,任务都在这里跑,机器性能需要好点;通常都有很多个,可以不断加机器扩大集群;每个工作节点由主节点管理重要概念 Pod
K8S
调度、管理的最小单位,一个 pod
可以包含一个或多个容器,每个 Pod 有自己的虚拟 IP。一个工作节点可以有多个 pod
,主节点会考量负载自动调度 pod 到哪个节点运行
部署应用到集群中
Deployment
创建一组pod
(由多个 Docker 容器组成) 的集合 Deployments | Kubernetes
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: # 定义容器,可以多个 containers: - name: test-k8s # 容器名字 image: ccr.ccs.tencentyun.com/k8s-tutorial/test-k8s:v1 # 镜像
Deployment 通过 label 关联起来 Pods
Service
定义不同Deployment
之间访问的方方式以及外部访问 Deployment
的方式 服务(Service) | Kubernetes
apiVersion: v1 kind: Service metadata: name: test-k8s spec: selector: app: test-k8s type: ClusterIP ports: - port: 8080 # 本 Service 的端口 targetPort: 8080 # 容器端口
服务的默认类型是
ClusterIP
,只能在集群内部访问,我们可以进入到 Pod 里面访问: kubectl exec -it pod-name -- bash
curl http://test-k8s:8080
对外暴露服务
上面我们是通过端口转发的方式可以在外面访问到集群里的服务,如果想要直接把集群服务暴露出来,我们可以使用NodePort
和 Loadbalancer
类型的 Service
apiVersion: v1 kind: Service metadata: name: test-k8s spec: selector: app: test-k8s # 默认 ClusterIP 集群内可访问,NodePort 节点可访问,LoadBalancer 负载均衡模式(需要负载均衡器才可用) type: NodePort ports: - port: 8080 # 本 Service 的端口 targetPort: 8080 # 容器端口 nodePort: 31000 # 节点端口,范围固定 30000 ~ 32767
ClusterIP
默认的,仅在集群内可用NodePort
暴露端口到节点,提供了集群外部访问的入口 端口范围固定 30000 ~ 32767LoadBalancer
需要负载均衡器(通常都需要云服务商提供,裸机可以安装 METALLB 测试) 会额外生成一个 IP 对外服务StatefulSet
StatefulSet
是用来管理有状态的应用,例如数据库。 前面我们部署的应用,都是不需要存储数据,不需要记住状态的,可以随意扩充副本,每个副本都是一样的,可替代的。 而像数据库、Redis
这类有状态的,则不能随意扩充副本。 StatefulSet
会固定每个 Pod
的名字 StatefulSet | Kubernetes
apiVersion: apps/v1 kind: StatefulSet metadata: name: mongodb spec: serviceName: mongodb replicas: 3 selector: matchLabels: app: mongodb template: metadata: labels: app: mongodb spec: containers: - name: mongo image: mongo:4.4 # IfNotPresent 仅本地没有镜像时才远程拉,Always 永远都是从远程拉,Never 永远只用本地镜像,本地没有则报错 imagePullPolicy: IfNotPresent --- apiVersion: v1 kind: Service metadata: name: mongodb spec: selector: app: mongodb type: ClusterIP # HeadLess clusterIP: None ports: - port: 27017 targetPort: 27017
StatefulSet 特性
Service
的CLUSTER-IP
是空的,Pod
名字也是固定的。
Pod
创建和销毁是有序的,创建是顺序的,销毁是逆序的。
Pod
重建不会改变名字,除了IP
,所以不要用IP直连
Service
名字连接,会随机转发请求
数据持久化
kubernetes
集群不会为你处理数据的存储,我们可以为数据库挂载一个磁盘来确保数据的安全。 你可以选择云存储、本地磁盘、NFS。
- 本地磁盘:可以挂载某个节点上的目录,但是这需要限定
pod
在这个节点上运行
- 云存储:不限定节点,不受集群影响,安全稳定;需要云服务商提供,裸机集群是没有的。
- NFS:不限定节点,不受集群影响
更高级的抽象
Storage Class (SC)
将存储卷划分为不同的种类,例如:SSD,普通磁盘,本地磁盘,按需使用。 Storage Classes | KubernetesapiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: slow provisioner: kubernetes.io/aws-ebs parameters: type: io1 iopsPerGB: "10" fsType: ext4
Persistent Volume (PV)
Persistent Volumes | KubernetesapiVersion: v1 kind: PersistentVolume metadata: name: mongodata spec: capacity: storage: 2Gi volumeMode: Filesystem # Filesystem(文件系统) Block(块) accessModes: - ReadWriteOnce # 卷可以被一个节点以读写方式挂载 persistentVolumeReclaimPolicy: Delete storageClassName: local-storage local: path: /root/data nodeAffinity: required: # 通过 hostname 限定在某个节点创建存储卷 nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - node2
Persistent Volume Claim (PVC)
PersistentVolumeClaim | KubernetesapiVersion: v1 kind: PersistentVolumeClaim metadata: name: mongodata spec: accessModes: ["ReadWriteOnce"] storageClassName: "local-storage" resources: requests: storage: 2Gi
为什么要这么多层抽象
- 更好的分工,运维人员负责提供好存储,开发人员不需要关注磁盘细节,只需要写一个申请单。
- 方便云服务商提供不同类型的,配置细节不需要开发者关注,只需要一个申请单。
- 动态创建,开发人员写好申请单后,供应商可以根据需求自动创建所需存储卷。
ConfigMap
数据库连接地址,这种可能根据部署环境变化的,我们不应该写死在代码里。Kubernetes
为我们提供了 ConfigMap
,可以方便的配置一些变量。ConfigMap | Kubernetes
apiVersion: v1 kind: ConfigMap metadata: name: mongo-config data: mongoHost: mongodb-0.mongodb
Secret
一些重要数据,例如密码、TOKEN,我们可以放到secret
中。Secret | Kubernetes
注意,数据要进行 Base64
编码 Base64编码、解码,BASE64转图片,图片转BASE64 - 在线工具
apiVersion: v1 kind: Secret metadata: name: mongo-secret # Opaque 用户定义的任意数据,更多类型介绍 https://kubernetes.io/zh/docs/concepts/configuration/secret/#secret-types type: Opaque data: # 数据要 base64。https://tools.fun/base64.html mongo-username: bW9uZ291c2Vy mongo-password: bW9uZ29wYXNz
使用方法
作为环境变量使用
apiVersion: apps/v1 kind: StatefulSet metadata: name: mongodb spec: replicas: 3 selector: matchLabels: app: mongodb template: metadata: labels: app: mongodb spec: containers: - name: mongo image: mongo:4.4 # IfNotPresent 仅本地没有镜像时才远程拉,Always 永远都是从远程拉,Never 永远只用本地镜像,本地没有则报错 imagePullPolicy: IfNotPresent env: - name: MONGO_INITDB_ROOT_USERNAME valueFrom: secretKeyRef: name: mongo-secret key: mongo-username - name: MONGO_INITDB_ROOT_PASSWORD valueFrom: secretKeyRef: name: mongo-secret key: mongo-password # Secret 的所有数据定义为容器的环境变量,Secret 中的键名称为 Pod 中的环境变量名称 # envFrom: # - secretRef: # name: mongo-secret
挂载为文件(更适合证书文件)
挂载后,会在容器中对应路径生成文件,一个key
一个文件,内容就是 value
, Secret | Kubernetes
apiVersion: v1 kind: Pod metadata: name: mypod spec: containers: - name: mypod image: redis volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true volumes: - name: foo secret: secretName: mysecret
Helm
Helm
类似 npm
,pip
,docker hub
, 可以理解为是一个软件库,可以方便快速的为我们的集群安装一些第三方软件。 使用 Helm 我们可以非常方便的就搭建出来 MongoDB / MySQL 副本集群,YAML 文件别人都给我们写好了,直接使用。官网,应用中心
安装 Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
安装 MongoDB 示例
# 安装
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install my-mongo bitnami/mongodb
# 指定密码和架构
helm install my-mongo bitnami/mongodb --set architecture="replicaset",auth.rootPassword="mongopass"
# 删除
helm ls
helm delete my-mongo
# 查看密码
kubectl get secret my-mongo-mongodb -o json
kubectl get secret my-mongo-mongodb -o yaml > secret.yaml
# 临时运行一个包含 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
# 进去 mongodb
mongo --host "my-mongo-mongodb" -u root -p mongopass
# 也可以转发集群里的端口到宿主机访问 mongodb
kubectl port-forward svc/my-mongo-mongodb 27017:27018
命名空间
如果一个集群中部署了多个应用,所有应用都在一起,就不太好管理,也可以导致名字冲突等。 我们可以使用namespace
把应用划分到不同的命名空间,跟代码里的 namespace
是一个概念,只是为了划分空间。
# 创建命名空间
kubectl create namespace testapp
# 部署应用到指定的命名空间
kubectl apply -f app.yml --namespace testapp
# 查询
kubectl get pod --namespace kube-system
Ingress
Ingress
为外部访问集群提供了一个 统一 入口,避免了对外暴露集群端口; 功能类似 Nginx
,可以根据域名、路径把请求转发到不同的 Service
。 可以配置 https
跟 LoadBalancer 有什么区别? LoadBalancer
需要对外暴露端口,不安全; 无法根据域名、路径转发流量到不同 Service
,多个 Service
则需要开多个 LoadBalancer
; 功能单一,无法配置 https
使用
要使用Ingress
,需要一个负载均衡器 + Ingress Controller
如果是裸机(bare metal
) 搭建的集群,你需要自己安装一个负载均衡插件,可以安装 METALLB 如果是云服务商,会自动给你配置,否则你的外部 IP 会是 “pending
” 状态,无法使用。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: simple-example spec: ingressClassName: nginx rules: - host: tools.fun http: paths: - path: /easydoc pathType: Prefix backend: service: name: service1 port: number: 4200 - path: /svnbucket pathType: Prefix backend: service: name: service2 port: number: 8080
标签:架构,name,mongodb,metadata,v1,集群,K8S,mongo From: https://www.cnblogs.com/ryanlamp/p/16924039.html