Blog

Kubernetes

Info

简介

它是一个为容器化应用提供集群部署和管理的开源工具,由Google开发。

Kubernetes这个名字源于希腊语,意为“舵手”或“飞行员”。Google在2014年开源了Kubernetes项目。

特性

  • 高可用,不宕机,自动灾难恢复
  • 灰度更新,不影响业务正常运转
  • 一键回滚到历史版本
  • 方便的伸缩扩展(应用伸缩,机器加减)、提供负载均衡
  • 有一个完善的生态

不同的应用部署方案

传统部署方式

应用直接在物理机上部署,机器资源分配不好控制,出现Bug时,可能机器的大部分资源被某个应用占用,导致其他应用无法正常运行,无法做到应用隔离。

虚拟机部署

在单个物理机上运行多个虚拟机,每个虚拟机都是完整独立的系统,性能损耗大。

容器部署

所有容器共享主机的系统,轻量级的虚拟机,性能损耗小,资源隔离,CPU和内存可按需分配。

应用场景

当你的应用只是跑在一台机器,直接docker + docker-compose就够了,方便轻松。

当你的应用需要跑在3,4台机器上,你依旧可以每台机器单独配置运行环境 + 负载均衡器。

当你应用访问数不断增加,机器逐渐增加到十几台、上百台、上千台时,每次加机器、软件更新、版本回滚,都会变得非常麻烦。这时候,Kubernetes就可以一展身手了,让你轻松管理百万千万台机器的集群。

Kubernetes可以为你提供集中式的管理集群机器和应用,加机器、版本升级、版本回滚,那都是一个命令就搞定的事,不停机的灰度更新,确保高可用、高性能、高扩展。

集群架构

master

主节点,控制平台,不需要很高性能,不跑任务,通常一个就行了,也可以开多个主节点来提高集群可用度。

worker

工作节点,可以是虚拟机或物理计算机,任务都在这里跑,机器性能需要好点;通常都有很多个,可以不断加机器扩大集群;每个工作节点由主节点管理。

重要概念Pod

豆荚,K8S调度、管理的最小单位,一个Pod可以包含一个或多个容器,每个Pod有自己的虚拟IP。一个工作节点可以有多个Pod,主节点会考量负载自动调度Pod到哪个节点运行。

组件

  • kube-apiserver:API服务器,公开了Kubernetes API。
  • etcd:键值数据库,可以作为保存Kubernetes所有集群数据的后台数据库。
  • kube-scheduler:调度Pod到哪个节点运行。
  • kube-controller:集群控制器。
  • cloud-controller:与云服务商交互。

Installation

Minikube

只是一个K8S集群模拟器,只有一个节点的集群,只为测试用,master和worker都在一起。

https://minikube.sigs.k8s.io/docs/start/

# 启动集群
minikube start
# 查看节点。kubectl 是一个用来跟 K8S 集群进行交互的命令行工具
kubectl get node
# 停止集群
minikube stop
# 清空集群
minikube delete --all
# 安装集群可视化 Web UI 控制台
minikube dashboard

云平台Kubernetes

可视化搭建,只需简单几步就可以创建好一个集群。

优点:安装简单,生态齐全,负载均衡器、存储等都给你配套好,简单操作就搞定。

裸机安装(Bare Metal)

至少需要两台机器(主节点、工作节点个一台),需要自己安装Kubernetes组件,配置会稍微麻烦点。 可以到各云厂商按时租用服务器,费用低,用完就销毁。

缺点:配置麻烦,缺少生态支持,例如负载均衡器、云存储。

https://github.com/lework/kainstall

主节点需要组件

  • kubeadm:用来初始化集群的指令。
  • kubelet:在集群中的每个节点上用来启动Pod和容器等。
  • kubectl:用来与集群通信的命令行工具。

工作节点需要组件

https://kubernetes.io/zh-cn/docs/concepts/overview/components/#node-components

  • docker:Container Runtime。
  • kubelet:管理Pod和容器,确保他们健康稳定运行。
  • kube-proxy:网络代理,负责网络相关的工作。

开始安装

# 每个节点分别设置对应主机名
hostnamectl set-hostname master
hostnamectl set-hostname node1
hostnamectl set-hostname node2
# 所有节点都修改 hosts
vim /etc/hosts
10.0.0.17 node1
10.0.0.16 node2
10.0.0.7 master
# 所有节点关闭 SELinux
setenforce 0
sed -i --follow-symlinks 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux
# 所有节点确保防火墙关闭
systemctl stop firewalld
systemctl disable firewalld

添加安装源(所有节点):

# 添加 k8s 安装源
cat <<EOF > kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
mv kubernetes.repo /etc/yum.repos.d/

# 添加 Docker 安装源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安装所需组件(所有节点):

yum install -y kubelet-1.22.4 kubectl-1.22.4 kubeadm-1.22.4 docker-ce

启动 kubelet、docker,并设置开机启动(所有节点):

systemctl enable kubelet
systemctl start kubelet
systemctl enable docker
systemctl start docker

修改 docker 配置(所有节点):

# kubernetes 官方推荐 docker 等使用 systemd 作为 cgroupdriver,否则 kubelet 启动不了
cat <<EOF > daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "registry-mirrors": ["https://ud6340vz.mirror.aliyuncs.com"]
}
EOF
mv daemon.json /etc/docker/

# 重启生效
systemctl daemon-reload
systemctl restart docker

用Kubeadm初始化集群(仅在主节点跑):

# 初始化集群控制台 Control plane
# 失败了可以用 kubeadm reset 重置
kubeadm init --image-repository=registry.aliyuncs.com/google_containers

# 记得把 kubeadm join xxx 保存起来
# 忘记了重新获取:kubeadm token create --print-join-command

# 复制授权文件,以便 kubectl 可以有权限访问集群
# 如果你其他节点需要访问集群,需要从主节点复制这个文件过去其他节点
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

# 在其他机器上创建 ~/.kube/config 文件也能通过 kubectl 访问到集群

把工作节点加入集群(只在工作节点跑):

kubeadm join 10.0.0.7:6443 --token wugfis.i5gatkabv547d2rl --discovery-token-ca-cert-hash sha256:ebde12fc5c7ff9036f8ce5fb10e649743fc884b176fd9b332243e3df54a3130e 

安装网络插件,否则node是NotReady状态(主节点跑):

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

Flannel is an open-source virtual network project managed by CoreOS network designed for Kubernetes. Each host in a flannel cluster runs an agent called flanneld. It assigns each host a subnet, which acts as the IP address pool for containers running on the host. Containers can then contact other containers directly, using their IP address. Flannel supports multiple backends for encapsulating packets. The recommended choice is Virtual Extensible LAN (VXLAN), which runs a Layer 2 network on top of a Layer 3 infrastructure. Flannel also supports host-gw, which maps direct routes between hosts in a manner similar to Calico.

查看节点,要在主节点查看(其他节点有安装Kubectl也可以查看):

[root@VM-0-7-centos ~]# kubectl get node
NAME     STATUS     ROLES                  AGE     VERSION
master   NotReady   control-plane,master   2m43s   v1.22.4
node1    NotReady   <none>                 33s     v1.22.4
node2    NotReady   <none>                 18s     v1.22.4
[root@VM-0-7-centos ~]# kubectl get node
NAME     STATUS   ROLES                  AGE     VERSION
master   Ready    control-plane,master   4m54s   v1.22.4
node1    Ready    <none>                 2m44s   v1.22.4
node2    Ready    <none>                 2m29s   v1.22.4

删除节点:

# master 删除节点
kubectl  delete nodes node1

# 在被删除的 node 节点中清空集群数据信息
kubeadm reset

在集群中查看集群的token值:

kubeadm token create --print-join-command

部署应用到集群

方式

直接命令

kubectl run testapp --image=ccr.ccs.tencentyun.com/k8s-tutorial/test-k8s:v1
[root@VM-0-7-centos ~]# kubectl get pod
NAME      READY   STATUS              RESTARTS   AGE
testapp   0/1     ContainerCreating   0          28s

Pod

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

Deployment

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。

部署应用演示

# 部署应用
kubectl apply -f app.yaml
# 查看 deployment
kubectl get deployment
# 查看 pod
kubectl get pod -o wide
# 查看 pod 详情
kubectl describe pod pod-name
# 查看 log
kubectl logs pod-name
# 进入 Pod 容器终端, -c container-name 可以指定进入哪个容器。
kubectl exec -it pod-name --bash
# 伸缩扩展副本
kubectl scale deployment test-k8s --replicas=5
# 把集群内端口映射到节点
kubectl port-forward pod-name 8090:8080
# 查看历史
kubectl rollout history deployment test-k8s
# 回到上个版本
kubectl rollout undo deployment test-k8s
# 回到指定版本
kubectl rollout undo deployment test-k8s --to-revision=2
# 删除部署
kubectl delete deployment test-k8s
# 查看全部
kubectl get all
# 重新部署
kubectl rollout restart deployment test-k8s
# 命令修改镜像,--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 get deployment test-k8s -o yaml >> app2.yaml
# 删除全部资源
kubectl delete all --all

更多介绍:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/

将Pod指定到某个节点运行:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector

限定CPU、内存总量:https://kubernetes.io/zh/docs/concepts/policy/resource-quotas/#%E8%AE%A1%E7%AE%97%E8%B5%84%E6%BA%90%E9%85%8D%E9%A2%9D

工作负载分类

https://kubernetes.io/zh-cn/docs/concepts/workloads/

  • Deployment:适合无状态应用,所有Pod等价,可替代。
  • StatefulSet:有状态的应用,适合数据库这种类型。
  • DaemonSet:在每个节点上跑一个Pod,可以用来做节点监控、节点日志收集等。
  • Job & CronJob:Job用来表达的是一次性的任务,而CronJob会根据其时间规划反复运行。

Service

特性

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

创建Service

创建一个Service,通过标签test-k8s跟对应的Pod关联上。

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: test-k8s
spec:
  selector:
    app: test-k8s
  type: ClusterIP
  ports:
    - port: 8080        # 本 Service 的端口
      targetPort: 8080  # 容器端口
# 应用配置
kubectl apply -f service.yaml
# 查看服务
kubectl get svc
# 查看服务详情,可以发现 Endpoints 是各个 Pod 的 IP,也就是他会把流量转发到这些节点
kubectl describe svc test-k8s
# 服务的默认类型是 ClusterIP,只能在集群内部访问,我们可以进入到 Pod 里面访问
kubectl exec -it pod-name -- bash
curl http://test-k8s:8080
# 如果要在集群外部访问,可以通过端口转发实现(只适合临时测试用)
kubectl port-forward service/test-k8s 8888:8080
# 如果你用 minikube,也可以这样
minikube service test-k8s

对外暴露服务

上面我们是通过端口转发的方式可以在外面访问到集群里的服务,如果想要直接把集群服务暴露出来,我们可以使用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

应用配置kubectl apply -f service.yaml。在节点上,我们可以curl http://localhost:31000/hello/easydoc访问到应用 并且是有负载均衡的,网页的信息可以看到被转发到了不同的Pod。

Loadbalancer也可以对外提供服务,这需要一个负载均衡器的支持,因为它需要生成一个新的IP对外服务,否则状态就一直是"pendding",这个很少用了,后面我们会讲更高端的Ingress来代替它。

多端口

对于某些服务,你需要公开多个端口。Kubernetes允许你在Service对象上配置多个端口定义。为服务使用多个端口时,必须提供所有端口名称,以使它们无歧义。必须配置name。

https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/#multi-port-services

apiVersion: v1
kind: Service
metadata:
  name: test-k8s
spec:
  selector:
    app: test-k8s
  type: NodePort
  ports:
    - port: 8080        # 本 Service 的端口
      name: test-k8s    # 必须配置
      targetPort: 8080  # 容器端口
      nodePort: 31000   # 节点端口,范围固定 30000 ~ 32767
    - port: 8090
      name: test-other
      targetPort: 8090
      nodePort: 32000

总结

ClusterIP

默认的,仅在集群内可用。

NodePort

暴露端口到节点,提供了集群外部访问的入口。

端口范围固定30000 ~ 32767。

LoadBalancer

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

K8S支持的负载均衡器:负载均衡器

Headless

适合数据库。ClusterIP设置为None就变成Headless了,不会再分配IP,后面会再讲到具体用法。

https://kubernetes.io/zh/docs/concepts/services-networking/service/#headless-services

StatefulSet

介绍

StatefulSet是用来管理有状态的应用,例如数据库。

前面我们部署的应用,都是不需要存储数据,不需要记住状态的,可以随意扩充副本,每个副本都是一样的,可替代的。

而像数据库、Redis这类有状态的,则不能随意扩充副本。

StatefulSet会固定每个Pod的名字。

特性

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

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

部署StatefulSet类型的Mongodb

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

kubectl apply -f mongo.yaml

Web应用连接Mongodb

在集群内部,我们可以通过服务名字访问到不同的服务。

指定连接第一个:mongodb-0.mongodb

数据持久化

介绍

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

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

HostPath

把节点上的一个目录挂载到Pod,但是已经不推荐使用了。

https://kubernetes.io/zh/docs/concepts/storage/volumes/#hostpath

配置方式简单,需要手动指定Pod跑在某个固定的节点。

仅供单节点测试使用;不适用于多节点集群。

Minikube提供了HostPath存储。

https://minikube.sigs.k8s.io/docs/handbook/persistent_volumes/

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
          volumeMounts:
            - mountPath: /data/db # 容器里面的挂载路径
              name: mongo-data    # 卷名字,必须跟下面定义的名字一致
      volumes:
        - name: mongo-data              # 卷名字
          hostPath:
            path: /data/mongo-data      # 节点上的路径
            type: DirectoryOrCreate     # 指向一个目录,不存在时自动创建

更高级的抽象

为什么要这么多层抽象

  • 更好的分工,运维人员负责提供好存储,开发人员不需要关注磁盘细节,只需要写一个申请单。
  • 方便云服务商提供不同类型的,配置细节不需要开发者关注,只需要一个申请单。
  • 动态创建,开发人员写好申请单后,供应商可以根据需求自动创建所需存储卷。

Storage Class (SC)

将存储卷划分为不同的种类,例如:SSD,普通磁盘,本地磁盘,按需使用。

https://kubernetes.io/zh-cn/docs/concepts/storage/storage-classes/

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
  type: io1
  iopsPerGB: "10"
  fsType: ext4

Persistent Volume (PV)

描述卷的具体信息,例如磁盘大小,访问模式。

https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/

https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes

https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#local

apiVersion: 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)

对存储需求的一个申明,可以理解为一个申请单,系统根据这个申请单去找一个合适的PV。还可以根据PVC自动创建PV。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongodata
spec:
  accessModes: ["ReadWriteOnce"]
  storageClassName: "local-storage"
  resources:
    requests:
      storage: 2Gi

ConfigMap & Secret

ConfigMap

数据库连接地址,这种可能根据部署环境变化的,我们不应该写死在代码里。 Kubernetes为我们提供了ConfigMap,可以方便的配置一些变量。

https://kubernetes.io/zh-cn/docs/concepts/configuration/configmap/

configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: mongo-config
data:
  mongoHost: mongodb-0.mongodb
# 应用
kubectl apply -f configmap.yaml
# 查看
kubectl get configmap mongo-config -o yaml

Secret

一些重要数据,例如密码、TOKEN,我们可以放到secret中。

https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/

data字段中所有键值都必须是base64编码的字符串。

secret.yaml

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
# 应用
kubectl apply -f secret.yaml
# 查看
kubectl get secret mongo-secret -o yaml

使用方法

作为环境变量使用

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。

https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod

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

Helm类似npm,pip,docker hub, 可以理解为是一个软件库,可以方便快速的为我们的集群安装一些第三方软件。

使用Helm我们可以非常方便的就搭建出来MongoDB / MySQL 副本集群,YAML文件别人都给我们写好了,直接使用。

https://helm.sh/zh/

https://artifacthub.io/

安装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
heml 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

可以用kubens快速切换namespace。

# 切换命名空间
kubens kube-system
# 回到上个命名空间
kubens -
# 切换集群
kubectx minikube

Ingress

介绍

Ingress为外部访问集群提供了一个统一入口,避免了对外暴露集群端口。功能类似Nginx,可以根据域名、路径把请求转发到不同的Service。 可以配置https。

跟LoadBalancer有什么区别?

  • LoadBalancer需要对外暴露端口,不安全。
  • 无法根据域名、路径转发流量到不同Service,多个Service则需要开多个 LoadBalancer。
  • 功能单一,无法配置https。

使用

要使用Ingress,需要一个负载均衡器 + Ingress Controller。

如果是裸机(bare metal)搭建的集群,你需要自己安装一个负载均衡插件,可以安装METALLB

如果是云服务商,会自动给你配置,否则你的外部IP会是"pending"状态,无法使用。

文档:https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/

Minikube中部署Ingress Controller:https://kubernetes.io/zh/docs/tasks/access-application-cluster/ingress-minikube/

Helm 安装:https://kubernetes.github.io/ingress-nginx/deploy/#quick-start

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

参考链接: