从k3s开始
k3s 是轻量级单节点集群,当然也可以加入多节点。
安装
curl -sfL https://get.k3s.io | sh -
# 中国区加速
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -
运行完就安装完成了,需要保证 6443 和 443 端口可用。
卷和存储
本地存储
添加一个 pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc # pvc的名字,可自定义
namespace: default
spec:
accessModes:
- ReadWriteOnce # 只能被单节点读写
storageClassName: local-path # k3s 内置的存储类,如果用 k8s 要自己添加 sc
resources:
requests:
storage: 2Gi
再添加一个使用 pvc 的 deployment:mysql.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql # 选择 app: mysql 标签的 pod
template: # 创建 pod 的模板
metadata:
labels:
app: mysql # 创建 pod 时添加 app: mysql 标签,以便 Deployment 可以识别
spec:
containers:
- image: mysql
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-volume # 和下面的 volumeMounts 一致才能 bind
mountPath: /var/lib/mysql # mysql的 data 所在位置
volumes:
- name: mysql-volume # 和上面的 volumeMounts 一致才能bind
persistentVolumeClaim:
claimName: mysql-pvc # 和刚刚的pvc保持一致
分别使用 kubectl apply 添加,pvc 没有 bind 的时候是 pending 状态,成功之后变成 bound
注意 mysql.yaml 的模板中 version 是 apps/v1,这是资源路径。
如果一直显示 pending 可以使用 kubectl describe pods <container_name> 查看原因,container_name需要 get pods 查看
例如这里一开始搞错了 pvc 名字,修正后 describe 得到成功。
但此时还不能访问 mysql,因为它目前只在集群内部使用
集群服务
集群内的 pod 需要变成 service 才能使用,有三种类型:
- ClusterIP Service:仅限集群内
- NodePort Service:集群外
- LoadBalancer Service:集群外+负载均衡
NodePort
NodePort 实际上并不推荐使用,推荐 LoadBalancer
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
selector:
app: mysql
ports:
- protocol: TCP # TCP|UDP
port: 3306 # 客户端访问服务的端口
targetPort: 3306 # 容器端口(mysql)
nodePort: 30000 # 在每个节点都开放30000,并转发到3306,省略则不分配
type: NodePort # ClusterIP|NodePort|LoadBalancer
注意 nodePort 要求30000-32767(可设置)
外部访问服务的路线为:外部–>30000–>3306(service)–>3306(pod)
LoadBalancer
一般推荐使用 loadbalancer:
apiVersion: v1
kind: Service
metadata:
name: mysql-lb-service
spec:
selector:
app: mysql
ports:
- protocol: TCP
port: 30001
targetPort: 3306
type: LoadBalancer
这时可以直接使用[集群外部IP:端口(30001)]访问。
ClusterIP
仅限集群内访问的 ClusterIP:
apiVersion: v1
kind: Service
metadata:
name: mysql-ci-service
spec:
selector:
app: mysql
ports:
- protocol: TCP # TCP|UDP
port: 30002
targetPort: 3306
type: ClusterIP
运行后得到:
一般来说会得到一个 CLUSTER-IP,这个 IP 不会变(自动路由到对应 pod),除非重启服务。
但推荐使用 Service Name 访问(这里是 mysql-ci-service)。这样 IP 变了也无所谓,此外 ClusterIP 还可以指定 IP。
深入:k8s 服务
本地调试
实践中关键数据库一般不会暴露到集群外,如 mysql,假设上面我们只有一个 mysql-ci-service 可用,怎么连上mysql 进行调试呢?
- port-forward:使用 kubectl 端口转发:可以转发到 pod 和服务,只转发端口
- proxy:通过 k8s api 访问集群服务,但只能访问 http 服务
- 使用 telepresence:推荐
port-forward
我们已知上面的service 名称为 mysql-ci-service,端口为 30002,则可以输入:
kubectl port-forward service/mysql-ci-service 3306:30002
就把本地端口转发到 service 的 30002,service 再转发到 pod 3306
如果要转发 pod(比如说可能想绕过 service 的负载均衡到达指定 pod),则需要得到 pod 名称,然后输入:
kubectl port-forward pod/mysql-6d57fdf866-f492r 3306:3306
proxy
输入 kubectl proxy 即可使用
telepresence
telepresence 可以直接拦截本地流量发送到 k8s 上,看起来就好像身处集群中。
telepresence connect
如果想要拦截云上服务的流量,telepresence 也能做到,详细参考文档。