前言
好久没写博客了,这三个月以来一直忙着学习k8s的知识,概念和名词是真的多。。。公司使用红帽提供的OpenShift平台,简单来说就是安全性更高,经过一点封装的k8s,然后我就负责在上面写deployment等manifest进行应用部署,而OpenShift本身则是系统团队负责搭建和维护的,不用应用运维团队关心。
就个人而言,这一年正好学习了很多分布式系统的知识,读了DDIA,啃过了MIT 6.824,实现了基于raft的分布式kv存储demo,最后这个项目甚至可以说就是k8s控制平面使用的etcd的原型了。事已至此,肯定是不满足于当下负责的云原生CICD工作的,更深入的理解k8s这门技术,是顺势而为且不得不做的事情。
最近换了新的笔记本,把第一次用工资购买的小新pro13给退役了,正好身边需要一台linux来装k8s进行个人学习(windows貌似也能装k8s,但估计会多出很多坑,不利于学习目标),那要不就把它刷成ubuntu,然后在上面装k8s吧,比买树莓派或者vps划算多了。
这篇博客主要就是记录在Ubuntu 22.04.3 LTS上安装kubernetes的过程,目前就这台笔记本单节点,后续估计也需要尝试拿其他机器做成多节点的,不然就没有用到k8s的核心能力了,在这里就先挖个坑吧。
用kubeadm安装集群
kubeadm是官方提供的kubernetes安装工具,当然第三方的工具也有,比如microk8s、k3s等,但出于学习的目的,我们就使用kubeadm吧,也不是特别复杂,基本按照官方文档,再google+chatgpt一下就能部署成功。
1. 安装Docker Engine
首先,一个k8s集群节点需要一个容器运行时(container runtime)来控制上面运行的容器,而实现了Container Runtime Interface,也就是CRI的软件都可以作为容器运行时,供k8s调用。因为我习惯使用docker,那么就使用docker engine作为CRI吧,这里是安装docker engine的文档。
2. 安装Cri-dockerd
然而由于docker engine并没有实现在他之后才提出的CRI标准,所以需要借助一个叫cri-dockerd的项目来作为适配器。按理说,docker engine使用containerd作为容器运行时,而containerd是实现CRI的,为什么还需要一个shim?在没有深入到项目去了解的情况下,我的理解是,我们希望实现的效果是k8s通过docker engine去操作containerd,而不是直接去控制containerd,所以需要docker engine去支持CRI。
3. 安装kubeadm
首先按照文档添加apt repo,然后使用apt来安装kubelet、kubeadm和kubectl
1
2
3
4
5
6
7
8
9
|
sudo apt-get update
# apt-transport-https may be a dummy package; if so, you can skip that package
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/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
|
4. 使用kubeadm init安装集群
接下来就可以使用kubeadm init <args>
安装k8s集群了,用几个args是必须要配置:
1
|
sudo kubeadm init --control-plane-endpoint="cp0.midk9t.com" --pod-network-cidr=10.244.0.0/16 --cri-socket="unix:///var/run/cri-dockerd.sock"
|
这里有三个配置项:
- criSocket=unix:///var/run/cri-dockerd.sock 配置k8s使用我们cri-dockerd的socket与容器运行时通信,而不是默认值unix:///var/run/containerd/containerd.sock
- podSunet=10.244.0.0/16 声明了集群内所有Pod使用的ip网段,这个ip段是我们后面使用的flannel cni所规定的
- controlPlaneEndpoint=cp0.midk9t.com:6443 这配置了控制平面所有节点公用的通信端点,可以是域名或者ip,这里我使用了一个解析到localhost的域名
然后不出意外的话就部署成功啦:
接下来需要安装一个CNI(container network interface),让k8s可以在维护集群虚拟网络,这里我们选用前面提到的flannel:
1
|
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
|
最后使用kubectl cluster-info
验证集群部署成功
由于目前只有ubuntu小新pro这台机器作为集群,所以需要应用的pod能被调度到control plane节点上:
1
|
kubectl taint node midk9t-lenovo-xiaoxinpro-13iml-2020 node-role.kubernetes.io/control-plane:NoSchedule-
|
默认情况下,control plane节点不允许跑应用的pod,这由taint机制来实现。
部署demo应用
成功在ubuntu上搭建集群后,我们来部署一个demo应用做最后验证:
1
|
kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
|
验证部署成功:
安装kubernetes-dashboard
首先需要安装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
|
然后通过helm安装kubernetes-dashboard
1
2
3
4
|
# Add kubernetes-dashboard repository
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
# Deploy a Helm Release named "kubernetes-dashboard" using the kubernetes-dashboard chart
helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --create-namespace --namespace kubernetes-dashboard
|
可以通过kubectl port-forward把pod暴露到ubuntu宿主机中
1
|
kubectl -n kubernetes-dashboard port-forward $kubernetes-dashboard-pod-name $hostport:8443
|
或者使用service暴露到宿主机中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
apiVersion: v1
kind: Service
metadata:
name: dashboard-service
namespace: kubernetes-dashboard
spec:
type: NodePort
selector:
app.kubernetes.io/name: kubernetes-dashboard
ports:
# 在pod中需要暴露的port
- targetPort: 8443
# 集群内访问的port
port: 8443
# 暴露到宿主机的Port
nodePort: 30443
|
接下来需要配置登录dashboard的权限,我们可以为dashboard创建一个service acount:
1
2
3
4
5
|
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
|
然后给它bind到cluster-admin这个role上,注意生产环境需要更严格的RBAC控制
1
2
3
4
5
6
7
8
9
10
11
12
|
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
|
最后使用kubectl -n kubernetes-dashboard create token admin-user
生成对应的token,就能登录进去dashboard了
结尾挖坑
把这篇旨在以后复现时使用的笔记记下后,下一步计划就是把k8s的一个重要玩法,也就是我目前负责的工作——云原生CICD流水线给记录下来。希望能趁热打铁,尽快填坑!