前言 Kubernetes 已经成为容器编排标准,没有 OpenStack 复杂而庞大的知识体系,但是需要老老实实学习的知识点也不少,由于 K8s 每年的改动也挺多,我这边文章暂时分享一些我觉得有用的链接,方便大家系统性学习和思考
更新历史 2020 年 07 月 03 日 - 增加 K8s 开源工具和参考文章 2020 年 05 月 30 日 - 更新 Kubernetes 跟着官方文档从零搭建 K8S 实践 2020 年 04 月 16 日 - 初稿
阅读原文 - https://liaojiaxin158.github.io/post/kubernetes/
Kubernetes 跟着官方文档从零搭建 K8S 本文将带领读者一起, 参照着 Kubernetes 官方文档, 对其安装部署进行讲解. Kubernetes 更新迭代很快, 书上、网上等教程可能并不能适用于新版本, 但官方文档能.
阅读这篇文章你能收获到:
如何阅读 Kubernetes 官方安装指南并搭建一个 Kubernetes 环境
Kubernetes 安装过程中的注意事项
避过常见的坑
阅读本文你需要:
熟悉 Linux 命令
知道 Kubernetes 是用来干什么的 (不然装它干啥(ಥ_ಥ))
知道 Docker
Before installing kubeadm
K8s 官网写的非常详细,列举实际操作的步骤供大家参考
This page shows how to install the kubeadm
toolbox. For information how to create a cluster with kubeadm once you have performed this installation process, see the Using kubeadm to Create a Cluster page.
服务器或虚拟机数量:2 机器配置: CPU >= 2, 内存 >= 2G 操作系统:本文为 CentOS 7 备注:根据不同操作系统需认真阅读和理解官方文档说明
One or more machines running one of:
Ubuntu 16.04+
Debian 9+
CentOS 7
Red Hat Enterprise Linux (RHEL) 7
Fedora 25+
HypriotOS v1.0.1+
Container Linux (tested with 1800.6.0)
2 GB or more of RAM per machine (any less will leave little room for your apps)
2 CPUs or more
Full network connectivity between all machines in the cluster (public or private network is fine)
Unique hostname, MAC address, and product_uuid for every node. See here for more details.
Certain ports are open on your machines. See here for more details.
Swap disabled. You MUST disable swap in order for the kubelet to work properly.
从官网找到kubeadm 安装文档入口 , 文档很详细. 英文阅读没有障碍的读者推荐直接查看英文文档, 中文文档不全且更新不及时安装时可能存在问题.
以下操作应用于 k8s-master 和 k8s-worker
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 45 46 hostnamectl set -hostname k8s-master hostnamectl set -hostname k8s-worker vim /etc/hosts 10.71.16.32 k8s-master 10.71.16.33 k8s-worker ifconfig -a cat /sys/class/dmi/id/product_uuid systemctl stop firewalld systemctl disable firewalld sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux setenforce 0 sestatus SELinux status: disabled vim /etc/fstab swapoff -a cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sudo sysctl --system lsmod | grep br_netfilter sudo modprobe br_netfilter
Installing runtime
选择安装 Docker, 注意阅读官网文档的推荐版本,若网络不好, 可换用国内源
Installing runtime
https://docs.docker.com/engine/install/centos/
https://kubernetes.io/docs/setup/production-environment/container-runtimes/#docker
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 45 46 47 48 # (Install Docker CE) ## Set up the repository ### Install required packages yum install -y yum-utils device-mapper-persistent-data lvm2 ## Add the Docker repository yum-config-manager --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo # Install Docker CE yum update -y && yum install -y \ containerd.io-1.2.13 \ docker-ce-19.03.8 \ docker-ce-cli-19.03.8 ## Create /etc/docker mkdir /etc/docker # Set up the Docker daemon cat > /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ] } EOF mkdir -p /etc/systemd/system/docker.service.d # Restart Docker systemctl daemon-reload systemctl restart docker # 利用 docker-cn 提供的镜像源 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://registry.docker-cn.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
Installing kubeadm, kubelet and kubectl Installing kubeadm, kubelet and kubectl
官网有一行配置是错误的,首次部署 K8s 时请移除改行,exclude=kubelet kubeadm kubectl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF setenforce 0 yum install -y kubelet kubeadm kubectl –disableexcludes=kubernetes systemctl enable –now kubelet
配置国内 kubeadm 源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 apt-get update && apt-get install -y apt-transport-https curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add - cat <<EOF >/etc/apt/sources.list.d/kubernetes.list deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main EOF apt-get update apt-get install -y kubelet kubeadm kubectl cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF setenforce 0 yum install -y kubelet kubeadm kubectl
初始化 k8s-master
以下操作应用于 k8s-master
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 kubeadm config print init-defaults > kubeadm-init.yaml vim kubeadm-init.yaml apiVersion: kubeadm.k8s.io/v1beta2 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 10.71.16.32 bindPort: 6443 nodeRegistration: criSocket: /var/run/dockershim.sock name: k8s-master taints: - effect: NoSchedule key: node-role.kubernetes.io/master --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta2 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: type : CoreDNS etcd: local : dataDir: /var/lib/etcd imageRepository: k8s.gcr.io kind: ClusterConfiguration kubernetesVersion: v1.18.0 networking: dnsDomain: cluster.local serviceSubnet: 10.96.0.0/12 scheduler: {} kubeadm config images pull --config kubeadm-init.yaml kubeadm init --config kubeadm-init.yaml Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME /.kube sudo cp -i /etc/kubernetes/admin.conf $HOME /.kube/config sudo chown $(id -u):$(id -g) $HOME /.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join 10.71.16.32:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:67e23b74df39cfca4dd0ba3d747139cb0dd4ea5c546a12c60e84b3c9b057fc6e kubectl get node NAME STATUS ROLES AGE VERSION k8s-master NotReady master 12m v1.18.3
配置网络,注意文档中的最新版本差异
create-cluster-kubeadm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 wget https://docs.projectcalico.org/manifests/calico.yaml cat kubeadm-init.yaml | grep serviceSubnet: serviceSubnet: 10.96.0.0/12 vim calico.yaml - name: CALICO_IPV4POOL_CIDR value: "10.96.0.0/12" kubectl apply -f calico.yaml kubectl get node NAME STATUS ROLES AGE VERSION k8s-master Ready master 15m v1.18.3
安装 Dashboard,注意官方文档的更新
Web UI (Dashboard)
1 2 3 4 5 6 7 kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml kubectl get pods --all-namespaces | grep dashboard kubernetes-dashboard dashboard-metrics-scraper-6b4884c9d5-79rvt 1/1 Running 0 4h5m kubernetes-dashboard kubernetes-dashboard-7b544877d5-zb4bl 1/1 Running 0 4h5m
创建用户,如果方便登录测试可以创建匿名账户
Creating sample user
创建一个用于登录 Dashboard 的用户. 创建文件 dashboard-adminuser.yaml 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kube-system --- 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: kube-system
执行命令 kubectl apply -f dashboard-adminuser.yaml
创建用于登录 Dashboard 的匿名用户. 创建文件 dashboard-annoymous.yaml 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: kubernetes-dashboard-anonymous rules: - apiGroups: [""] resources: ["services/proxy"] resourceNames: ["https:kubernetes-dashboard:"] verbs: ["get", "list" , "watch" , "create" , "update" , "patch" , "delete" ] - nonResourceURLs: ["/ui", "/ui/*" , "/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/*" ] verbs: ["get", "list" , "watch" , "create" , "update" , "patch" , "delete" ] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kubernetes-dashboard-anonymous roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: kubernetes-dashboard-anonymous subjects: - kind: User name: system:anonymous
执行命令 kubectl apply -f dashboard-annoymous.yaml.yaml
生成证书,这步非必须,根据情况生成并导入客户端
Accessing Dashboard
1 2 3 grep 'client-certificate-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.crt grep 'client-key-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.key openssl pkcs12 -export -clcerts -inkey kubecfg.key -in kubecfg.crt -out kubecfg.p12 -name "kubernetes-client"
第三条命令生成证书时会提示输入密码, 可以直接两次回车跳过
kubecfg.p12
即需要导入客户端机器的证书. 将证书拷贝到客户端机器上, 导入即可
需要注意的是: 若生成证书时跳过了密码, 导入时提示填写密码直接回车即可, 不要纠结密码哪来的
此时我们可以登录面板了, 访问地址: https://{k8s-master-ip}:6443/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login 登录时会提示选择证书, 确认后会提示输入当前用户名密码(注意是电脑的用户名密码)
登录 Dashboard
执行 kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
, 获取 Token.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}' ) Name: admin-user-token-wdj28 Namespace: kube-system Labels: <none> Annotations: kubernetes.io/service-account.name: admin-user kubernetes.io/service-account.uid: f97e69ff-c4aa-45d4-bbb2-5221f3fb43cc Type: kubernetes.io/service-account-token Data ==== ca.crt: 1025 bytes namespace: 11 bytes token: eyJhbGciOiJSUzI1NiIsImtpZCI6IlMxUGJ5TTR0cUQzd3JSODZfdWNScU14YXdHdmpLakdwSldrdTdhT1UyV2cifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLXdkajI4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJmOTdlNjlmZi1jNGFhLTQ1ZDQtYmJiMi01MjIxZjNmYjQzY2MiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06YWRtaW4tdXNlciJ9.wTdqAJfK0Z7C43SU0mAwoQw2dCdBcUD6A3uVo03OkW-r8Y630NP6MQqwmpi4IERohYjY6528oW0Ucj_2ukWu8z5eUAabNgL-_BQGXe2Zg1oGRK_LY90JN_L6f8mpYrPDFLfjSnUAdgb3zzCzhzIa2RihiYZW-mGm_ucfK5xt3dpFbDeIeEgePyFjUiX5ZdoMJEuerd6zgee1yeXEctQD4TRRxxtFebcLRgFDWVfOz0xWRNN1qSOB5v1ChkaQ5a6YxvGwjcrwrQaVN8bp73Zueu7FwmbkObT_EpWy0aZ7csTcSuNZ2K8QTpXr6NtN5xIcTpyMmIHmc9qCaskr5uM3qA
复制该 Token 到登录页, 点击登录即可
添加 k8s-worker
添加 Worker 节点,以下操作应用于 k8s-worker
重复执行 前期准备 - 修改 hostname
~ 安装 Kubernetes - 修改网络配置
的全部操作, 初始化一个 Worker 机器
1 2 3 4 5 6 7 8 # 执行如下命令将 Worker 加入集群,此处的秘钥是初始化 Master 后生成的 kubeadm join 10.71.16.32:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:67e23b74df39cfca4dd0ba3d747139cb0dd4ea5c546a12c60e84b3c9b057fc6e # 添加完毕后, 在 Master 上查看节点状态 kubectl get node NAME STATUS ROLES AGE VERSION k8s-master Ready master 10h v1.18.3 k8s-worker Ready <none> 96s v1.18.3
https://github.com/kubernetes/dashboard
Kubernetes(一) 跟着官方文档从零搭建 K8S
Kubernetes 应用部署 本文将与读者一起, 学习如何在 Kubernetes 上部署应用. 包括: 如何部署应用、发布文件讲解、将本地项目打包发布等.
阅读这篇文章你能收获到:
学会如何在 k8s 部署应用
如何打包 Docker 镜像、上传到私有库
阅读本文你需要:
熟悉 Linux 命令
有一个 Kubernetes 环境
理解描述文件 首先, 我们通过在 Kubernetes 部署 Nginx 来理解描述文件.
一般地, Kubernetes 使用 yaml(或 json)来描述发布配置. 下面是一个简单的描述文件: nginx-pod.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 apiVersion: v1 kind: Pod metadata: name: nginx-pod labels: app: nginx-pod env: test spec: containers: - name: nginx-pod image: nginx:1.18 imagePullPolicy: IfNotPresent ports: - containerPort: 80 restartPolicy: Always
我们登录 Master 节点, 使用 kubectl
命令来部署这个文件所描述的应用. (当然, 使用 dashboard 发布也可)
1 2 3 4 5 6 kubectl apply -f nginx-pod.yaml pod/nginx-pod created kubectl get pods NAME READY STATUS RESTARTS AGE nginx-pod 1/1 Running 0 39s
kubectl get pods
命令是用来查看 pod 列表的, 使用 grep
筛选出 nginx 相关的 pod. 此时 nginx 已经发布完成了. 我们可以从 dashboard 来直观地查看到应用状态.
备注: 删除 pod 可使用 kubectl delete -f nginx-pod.yaml
命令, 也可直接在 dashboard 进行操作.
如何访问服务 上一小节我们部署了一个 Nginx pod, 但我们无法访问到该 Nginx.
想要访问到 pod 中的服务, 最简单的方式就是通过端口转发, 执行如下命令, 将宿主机的 9999
端口与 nginx-pod 的 80
端口绑定:
1 2 3 kubectl port-forward --address 0.0.0.0 nginx-pod 9999:80 Forwarding from 0.0.0.0:9999 -> 80 Handling connection for 9999
此时, 我们可以通过访问宿主机 9999 端口来访问 Nginx.
部署本地项目 将本地开发的项目发布到 Kubernetes, 需要将项目打包成 Docker 镜像, 然后将镜像推送到仓库(公开 / 私有仓库都可).
首先, 我们需要一个可以运行的本地项目, 笔者使用 spring-boot 构建了一个简单的 web 项目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @RestController @RequestMapping (value = "/k8s-test" )@SpringBootApplication public class K8sTestApplication { @GetMapping (value = "/timestamp" ) public ResponseEntity<?> getTimestamp() { return ResponseEntity.ok(System.currentTimeMillis() + "\n" ); } public static void main (String[] args) { SpringApplication.run(K8sTestApplication.class, args); } }
打包 Docker 镜像 Dockerfile reference
有了项目, 我们需要将其打包成一个 Docker 镜像, Dockerfile
内容如下:
1 2 3 4 FROM java:8-alpine COPY ./k8s-test-0.0.1-SNAPSHOT.jar /usr/app/ WORKDIR /usr/app ENTRYPOINT ["java", "-jar", "k8s-test-0.0.1-SNAPSHOT.jar"]
FROM java:8-alpine
: 该镜像基于 java-8-alpine
镜像.
COPY ./target/k8s-test-0.0.1-SNAPSHOT.jar /usr/app/
: 将编译打包好的 jar 拷贝到镜像的 /usr/app
目录下.
WORKDIR /usr/app
: 工作目录指定为 /usr/app
.
ENTRYPOINT ["java", "-jar", "k8s-test-0.0.1-SNAPSHOT.jar"]
: 启动 docker 时执行 java -jar k8s-test-0.0.1-SNAPSHOT.jar
命令
进入到 Dockerfile 所在目录执行 docker build -t piaoruiqing/k8s-test .
进行打包. 注意不要遗漏掉命令最后面的 .
, 它代表当前目录.
1 2 3 4 5 # 打包 docker build -t piaoruiqing/k8s-test . # 通过 docker images 命令可以查看本地镜像列表: docker images | grep k8s piaoruiqing/k8s-test latest efe9e9625376 4 minutes ago 174MB
推送到远程仓库 留空给 Harbor
Kubernetes(二) 应用部署
如何从外部访问服务 通过前文的讲解,《跟着官方文档从零搭建 K8S》、《应用部署》相信读者已经对 Kubernetes 安装及部署应用有了一定的了解. 接下来, 本文将针对如何将服务暴露给外部进行讲解.
阅读这篇文章你能收获到:
了解 Kubernetes 暴露服务的几种方案及其优缺点.
阅读本文你需要:
了解基本的 Kubernetes 命令
有一个 Kubernetes 环境
将服务暴露给外部客户端的几种方式
通过 port-forward
转发, 这种方式在之前的文章中有提到过, 操作方便、适合调试时使用, 不适用于生产环境 .
通过 NodePort
, 此时集群中每一个节点 (Node) 都会监听指定端口, 我们通过任意节点的端口即可访问到指定服务. 但过多的服务会开启大量端口难以维护.
通过 LoadBalance
来暴露服务. LoadBalance(负载均衡 LB)
通常由云服务商提供, 如果云环境中不提供 LB 服务, 我们通常直接使用 Ingress
, 或使用 MetalLB
来自行配置 LB.
通过 Ingress
公开多个服务. Ingress
公开了从群集外部到群集内 services
的 HTTP 和 HTTPS 路由. 流量路由由 Ingress
资源上定义的规则控制. 在云服务商不提供 LB 服务的情况下, 我们可以直接使用 Ingress
来暴露服务. (另外, 使用 LB + Ingress
的部署方案可以避免过多 LB 应用带来的花费).
Kubernetes(三) 如何从外部访问服务
K8s 开源管理产品推荐 kubeasz
kuboard
KubeSphere
cert-manager
参考文章 Kubernetes Documentation
Google Kubernetes Engine 文档
Kubernetes Handbook
Kubernetes 指南
和我一步步部署 kubernetes 集群
才云开源内部 Kubernetes 学习路径
深入剖析 Kubernetes