Kubernetes 学习(K3d)
随着 Kubernetes 及其周边生态的发展,云原生技术现在已经很成熟流行了,不过 Kubernetes 架构复杂,使用门槛较高,即使自己学习的话安装一个 Kubernetes 集群也是很麻烦的事情。好在大多云厂商比如阿里腾讯云都有提供现成的容器服务,可以直接创建使用,也有一些项目简化模拟了 Kubernetes,如 Kind、Minikube 和 K3d 等,可以供开发者在本地学习和开发调试。
K3s 是一个轻量级 Kubernetes,K3d,全称 K3s in Docker,在 Docker 环境的运行的 K3s,可以在 Docker 容器中构建多个 K3s 节点,单个物理机可以运行多个 K3s 集群,每个集群可拥有多台 Server 和 Agent 节点。
k3s 包括以下一些组件:
- Containerd:一个类似 Docker 的运行时容器,但是它不支持构建镜像;
- Flannel:基于 CNI 实现的网络模型,默认使用的是 Flannel,也可以使用 Calico 等其他实现替换;
- CoreDNS:集群内部 DNS 组件;
- SQLite3:默认使用 SQLite3 进行存储,同样也支持 etcd3, MySQL, Postgres;
- Traefik:默认安装 Ingress controller 是 traefik 1.x 的版本;
- Embedded service loadbalancer:内嵌的一个服务负载均衡组件。
相关工具安装
K3d 项目地址 https://github.com/k3d-io/k3d,安装:
1 | wget -q -O - https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash |
kubectl 是 Kubernetes 命令行工具,下载后建立软链接。
1 | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" |
使用 kubectl 终端和系统不要有代理,以免影响和 K3s 集群的通讯。
kubecm是一个k8s多集群配置管理工具。
1 | curl kubecm.tar.gz https://github.com/sunny0826/kubecm/releases/download/v$\{VERSION\}/kubecm_$\{VERSION\}_Linux_x86_64.tar.gz |
helm 是 Kubernetes 包管理工具,下载脚本执行安装。
1 | curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 |
创建集群
用命令和指定配置文件创建集群
以下命令是创建一个一主两从的集群。
1 | k3d cluster create command-cluster --port 8080:80@loadbalancer --port 8443:443@loadbalancer --api-port 6443 --servers 1 --agents 2 |
重点来看使用 yaml 配置文件创建集群,编写一个 dev-cluster.yaml 文件,内容如下。
老的 v1alpha2 版本和 v1alpha4 版本配置有些差异,具体看 K3d 的官方文档。
1 | apiVersion: k3d.io/v1alpha4 |
指定 yaml 文件创建集群:
1 | $ k3d cluster create --config dev-cluster.yaml |
成功看下集群信息:
1 | $ kubectl cluster-info |
节点信息:
1 | $ kubectl get node |
安装 Traefik2 网关
Ingress 一个API对象,就如同其他的API对象Service、Deployment一样,负责管理外部流量对于集群内部的访问,能用来做负载均衡,搞 SSL 等。Ingress Controller 有 Traefik、Nginx Ingress、kong、istio 等等。
我们可以直接使用 Helm 来安装 Traefik2。
1 | # 跟apt安装应用的流程相似 |
等待安装完毕,查看 pod 可以看装完了没有。
1 | $ helm install traefik traefik/traefik |
因为集群是跑在 docker 中,访问需要做端口转发:
1 | kubectl port-forward --address=0.0.0.0 $(kubectl get pods --selector "app.kubernetes.io/name=traefik" --output=name) 9000:9000 |
通过 http://0.0.0.0:9000/dashboard/#/ 访问仪表盘。
部署应用
基本概念:
- Pod:Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元
- Deployment:用于管理Pod、ReplicaSet,可实现滚动升级和回滚应用、扩容和缩容。
- Label:Label以key/value键值对的形式附加到各种对象上,如Pod、Service、RC、Node等。
- Service:定义了一个服务的访问入口地址,前端的应用通过这个入口地址访问其背后的一组由Pod副本组成的集群实例,来自外部的访问请求被负载均衡到后端的各个容器应用上。Service与其后端Pod副本集群之间则是通过Label Selector实现关联。简单来说前端请求不是直接发送给Pod,而是发送到Service,Service再将请求转发给pod。
我们先随便写个 python 程序放到 Docker,并 push 到镜像库上。
1 | # 简单的python程序,接收get请求,返回heah的内容 |
编写Dockerfile:
1 | FROM python:3.8-alpine |
打包镜像,打 tag,push 到 dockerhub。
1 | docker build -t py-server . |
编写部署应用的 yaml 文件 demo.yaml,分别有两个 Deployment,py-server-1 一个副本,py-server-2 两个副本,对应两个 Service,还有一个 Ingress 用来管理外部访问。
使用 kubectl apply -f /path/demo.yaml
命令部署。
1 | $ kubectl apply -f demo.yaml |
部署完毕来看下节点信息:
1 | $ kubectl get pod |
我们修改本地的 hosts,解析两个 example 域名,命令vi /etc/hosts
,添加以下内容。
1 | # local k3d test |
还记得前面创建集群的 yaml 文件中,- port: 8080:80 # ingress端口映射
这一行把80端口映射到了宿主机8080(当然80也可以,我只是本地80有其他应用用到不想停掉而已),所以在浏览器用域名访问要用8080的端口,即 http://demo1.example.com:8080/ 和 http://demo2.example.com:8080/ 。或者用 curl 测试:
1 | $ curl http://demo1.example.com:8080/ |
我们还可以修改下 Python 程序和 Dockerfile 文件,把程序日志输出到日志,然后 kubectl exec -it py-server-2-79bd86f9d5-64cqg sh
进入 pod 具体的两个容器,看看两个 py-server-2 程序的日志,多次访问 demo2.example.com:8080,看看有没有做负载均衡,这里就不在做测试了。
参考
- [1] K3d 文档
- [2] Kubernetes 文档
- [3] 如何在本地快速启动一个 K8S 集群
- [4] 使用k3d启动k3s集群
- [5] Docker Hub镜像公共仓库使用