K8S学习笔记

K8S基础知识,概念以及操作。

简介

Kubernetes(K8S)是一个容器编排管理系统,那么为什么要用K8S呢?因为它有如下功能:

  • 服务发现和负载均衡
  • 存储编排
  • 自动化部署和回滚
  • 自动装箱优化
  • 自我修复
  • 密钥和配置管理
  • ……

想要学习Kubernetes,首先得有一个Kubernetes的环境,而K8S的部署又相当棘手,不仅需要硬件资源,而且部署步骤极其繁琐。minikube是一个简化的K8S,致力于让学习和开发K8S更加简单。所以,学习K8S,我们可以先从minikube入手。

接下来,本文将分为两个大方面,去介绍K8S:

  • K8S的基础概念
  • K8S的使用方法

基础概念

K8S术语

概念 解释
Pod Pod是K8S中的最小单位,是一个抽象概念,由一个或者多个容器组成,共享Pod中的网络和存储资源。
Deployment Deployment是一种抽象,用于声明式地更新Pod和ReplicaSet。
Stateful
Job
CronJob
Service Service也是一种抽象概念,用于将Pod暴露到网络上。其类型包括:ClusterIP,NodePort,LoadBalancer,ExternalName。
Ingress
Namespace 命名空间,用于隔离同一集群中不同用途的资源。
ConfigMap 用于存储应用程序的配置,和代码隔离开。
Secret

K8S核心组件

上图是K8S官网对于核心组件的介绍,这些组件分别是:

  • API Server
  • Cloud Controller Manager(可选)
  • Controller Manager
  • etcd(持久化存储)
  • kubelet
  • kube-proxy
  • Scheduler
  • Node

虚线区域是控制面,主要是和K8S控制相关的组件。一般实践中,我们把Node分为Master Node和Worker Node,Master Node上一般运行控制面的组件,Worker Node负责运行实际的容器。

API Server(kube-apiserver)是K8S对外暴露的控制方式,本质是一个HTTP服务,让你通过HTTP交互来控制K8S的行为方式;无论你使用kubectl还是Dashboard,都是通过kube-apiserver控制K8S的。

Cloud Controller Manager(cloud-controller-manager)主要是和特定云服务相关的,暂时跳过。

逻辑上,控制器(kube-controller-manager)是多个分离的进程,但是为了减少复杂性,这些控制器被编译成了一个二进制文件,并且运行在一个进程中,这些控制器有很多,比如:节点控制器,工作控制器,服务账号控制器等。

etcd是一个键值对存储服务,可以提供持久化和高可用的存储,主要用于存储K8S集群的所有数据,千万记得备份etcd中的数据。

kubelet运行在Worker节点上,确保容器运行在Pod中,并和PodSpec中的定义一致,但是并不管理非K8S创建的容器。

kube-proxy运行在Worker节点上,实现了K8S中的Service概念,主要用于管理网络规则。

容器运行时管理容器的执行和生命周期,可以是任何符合K8S CRI(Container Runtime Interface)规范的实现,比如:containerd,或者CRI-O。

了解这些组件是必须的,这样你才能理解它的工作方式。

K8S对象

什么是K8S对象(Objects)?对象是K8S中的持久实体,用来表示集群的状态,Pod,Deployment和Service等都是对象。这些对象用Yaml(常用)或者Json格式的文本表示,使用客户端(比如Kubectl)通过API传输给API Server,存储在etcd中,K8S集群会确保,对象状态和你的描述保持一致。

工作负载

工作负载是对于Pod更高级的抽象,不同功能的应用需要选择不同的工作负载,常见的有:

  • Deployment(包括ReplicaSet)
  • StatefuleSet
  • DaemonSet
  • CronJob
  • Job

Pod生命周期

Value Description
Pending The Pod has been accepted by the Kubernetes cluster, but one or more of the containers has not been set up and made ready to run. This includes time a Pod spends waiting to be scheduled as well as the time spent downloading container images over the network.
Running The Pod has been bound to a node, and all of the containers have been created. At least one container is still running, or is in the process of starting or restarting.
Succeeded All containers in the Pod have terminated in success, and will not be restarted.
Failed All containers in the Pod have terminated, and at least one container has terminated in failure. That is, the container either exited with non-zero status or was terminated by the system.
Unknown For some reason the state of the Pod could not be obtained. This phase typically occurs due to an error in communicating with the node where the Pod should be running.

容器生命周期

  • Waiting
  • Running
  • Terminated

使用方法

安装minikube

首先,我们要部署一个minikube环境,第一步,当然是安装,我用的是ArchLinux,用pacman安装即可:

1
pacman -S minikube

启动minikube服务

在启动之前,你需要先配置一个代理,否则无法访问K8S Registry。启动命令为:

1
2
3
4
5
export HTTP_PROXY=http://<proxy hostname:port>
export HTTPS_PROXY=https://<proxy hostname:port>
# 以下IP为K8S内部使用IP,不需要代理
export NO_PROXY=localhost,127.0.0.1,10.96.0.0/12,192.168.59.0/24,192.168.49.0/24,192.168.39.0/24
minikube start

这样,你就启动了一个minibue服务。

开始使用

现在我们就可以使用kubectl控制了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 获取所有的Pod
kubectl get pod -A

# 部署一个Deployment
kubectl apply -f deployment.yaml

# 暴露Service
kubectl expose deployment nginx --type="NodePort" --port 8080

# 扩容你的Deployment
kubectl scale deployment nginx --replicas 3

# 更新
kubectl set image deployment nginx nginx=nginx:latest

# 回滚
kubectl rollout undo deployment nginx

安装Kubernetes

手动安装Kubernetes是一项非常繁琐的事项,如果想要顺利完成,需要仔细看官方文档。为了方便,我选择在Ubuntu上安装,并且只记录重要的步骤。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# Kubernetes Version: 1.29
# 准备工作
# 关闭Swap
sudo swapoff -a
# 加载相关的内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 配置内核参数
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
sudo sysctl --system
# 安装容器运行时
sudo apt install containerd
# 修改cgroup driver配置(kubelet和CRI的cgroup driver要一致,否则控制面Pod会不断重启)
# https://kubernetes.io/docs/setup/production-environment/container-runtimes/#cgroup-drivers
# https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd-systemd
# 安装kubeadm/kubelet/kubectl
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
sudo systemctl enable --now kubelet
# 为Containerd配置代理,拉取k8s需要的镜像
# 初始化控制面
sudo kubeadm init --apiserver-advertise-address 192.168.1.100 --apiserver-bind-port 6443 --apiserver-cert-extra-sans 192.168.1.100,k8s.example.com --control-plane-endpoint 192.168.1.100:6443 --node-name master --image-repository registry.k8s.io --pod-network-cidr 10.10.0.0/16 --service-cidr 10.11.0.0/16
# 复制kubeconfig
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 部署Pod Network:https://kubernetes.io/docs/concepts/cluster-administration/addons/
# 加入节点
sudo kubeadm join 192.168.1.100:6443 --token xxxxxxxxx --discovery-token-ca-cert-hash sha256:xxxxxxxxx
# 允许控制面节点调度
kubectl taint nodes --all node-role.kubernetes.io/control-plane-

卸载Kubernetes

1
2
3
4
5
6
# 删除节点
kubectl drain <node name> --delete-emptydir-data --force --ignore-daemonsets
sudo kubeadm reset
kubectl delete node <node name>
# 删除控制面
sudo kubeadm reset

更新证书

默认情况下,k8s的证书有效期是一年,每年都需要renew一次,否则有些API接口会无法正常使用,更新过程如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 检查证书过期情况
kubeadm certs check-expiration
# 备份k8s配置
cp -r /etc/kubernetes /etc/kubernetes.bak
# 更新证书
kubeadm certs renew all
# 重启相关服务
# https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/#manual-certificate-renewal
docker ps | grep -E "k8s_kube-apiserver|k8s_kube-scheduler|k8s_kube-controller"|awk '{print $1}'|xargs docker restart
# restart etcd
cd /etc/kubernetes/manifests && mv etcd.yaml /tmp/ && wait 10 && mv /tmp/etcd.yaml .
# 更新kubeconfig
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

备份和恢复etcd数据

1
2
ETCDCTL_API=3 etcdctl snapshot save ...  
ETCDCTL_API=3 etcdctl snapshot restore ...

安装Helm

1
2
3
4
5
curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
sudo apt-get install apt-transport-https --yes
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm

安装Ingress NGINX Controller

1
2
3
helm upgrade --install ingress-nginx ingress-nginx \
	--repo https://kubernetes.github.io/ingress-nginx \
	--namespace ingress-nginx --create-namespace
1
2
# 使用Host Network暴露出80和443端口
kubectl -n ingress-nginx edit deployments ingress-nginx-controller
1
2
3
4
template:
	spec:
		hostNetwork: true
# 初次之外,删除--publish-service命令行参数

安装Dashboard

1
2
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --create-namespace --namespace kubernetes-dashboard

部署cert-manager

1
2
3
4
5
6
7
# 添加Helm仓库
helm repo add jetstack https://charts.jetstack.io --force-update
helm repo update
# 安装CRDs
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.4/cert-manager.crds.yaml
# 安装Chart
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.14.4 # --set installCRDs=true

总结

在K8S的使用中,最常用的是以下几个点:

  • K8S部署
  • K8S配置
  • 部署Deployment
  • 部署Service
  • 扩容
  • 更新和回滚

常见问题

安装完成后,无法执行port-forward和exec

我的情况是Vagrant VirtualBox Provider启动的两个虚拟机,eth0有同样的MAC和IP,导致INTERNAL-IP相同,让k8s工作异常,为kubelet配置--node-ip选项后解决。

重启后,kubelet没有创建apiserver Pod和etcd Pod

看日志后,发现kubelet无法打开/run/systemd/resolve/resolv.conf这个文件,执行sudo systemctl enable --now systemd-resolved.service解决。

工具

当你管理多个集群的时候,会涉及到切换不同的集群和不同的命名空间,推荐使用以下小工具,提高效率:

参考

Licensed under CC BY-NC-SA 4.0
最后更新于 2024-01-27
使用 Hugo 构建
主题 StackJimmy 设计