如果你读过该系列的 前一篇文章,那么在你的集群里应该已经成功运行着Gitea的deployment了。下一步是能够通过Web浏览器访问它。本文会介绍一些Kubernetes的网络基础知识,并且可以让外部网络可以访问Gitea容器。
打开容器端口
Gitea容器内的软件会监听3000端口上的http请求,以及22端口上的SSH链接。可以通过如下YAML文件打开这些端口:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: gitea-deployment
spec:
replicas: 1
selector:
matchLabels:
app: gitea
template:
metadata:
labels:
app: gitea
spec:
containers:
- name: gitea-container
image: gitea/gitea:1.4
ports: #+
- containerPort: 3000 #+
name: http #+
- containerPort: 22 #+
name: ssh
在集群里应用这个更新过的文件:
这时,就可以运行命令kubectl describe deployment来查看新打开的端口了。Pod应该已经打开了3000和22端口。$ kubectl apply -f gitea.yaml
$ kubectl describe deployment | grep Ports
Ports: 3000/TCP, 22/TCP
使用端口转发进行调试
# grab the name of your active pod
$ PODNAME=$(kubectl get pods --output=template \
--template="{{with index .items 0}}{{.metadata.name}}{{end}}")
# open a port-forward session to the pod
$ kubectl port-forward $PODNAME 3000:3000
这样,kubectl就会将本机3000端口的所有连接转发到云上的pod里。在浏览器打开 http://localhost:3000,你就可以和服务器交互了,服务器就像运行在本地一样。
创建外部LoadBanlancer
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: gitea-deployment
spec:
replicas: 1
selector:
matchLabels:
app: gitea
template:
metadata:
labels:
app: gitea
spec:
containers:
- name: gitea-container
image: gitea/gitea:1.4
ports:
- containerPort: 3000
name: http
- containerPort: 22
name: ssh
---
kind: Service #+
apiVersion: v1 #+
metadata: #+
name: gitea-service #+
spec: #+
selector: #+
app: gitea #+
ports: #+
- protocol: TCP #+
targetPort: 3000 #+
port: 80 #+
name: http #+
- protocol: TCP #+
targetPort: 22 #+
port: 22 #+
name: ssh #+
type: LoadBalancer #+
和Deployment一样,Service使用选择器(第29-30行)。这个选择器告诉LoadBanlancer将流量路由到哪些Pod里。当LoadBanlancer收到请求时,它会智能地将负载分发给匹配这个选择器的所有Pod。这里,因为我们仅有一个Pod,所以负载均衡很简单。
LoadBanlancer管理的端口定义在31-39行。除了定义一个唯一名称以及协议类型(TCP/UDP)之外,用户还必须定义“port”和“targetPort”。这两个字段定义了外部IP的端口(port)和容器使用端口(targetPort)的映射。在33和34行里,LoadBanlancer会监听80端口的请求(Web浏览器查看网页的默认端口),并且将请求转发给Pod的3000端口。
我们再次需要将更改应用到集群里:
等待几分钟变更生效后,检查服务:$ kubectl apply -f gitea.yaml
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL_IP AGE
gitea-service LoadBalancer 10.27.240.34 35.192.x.x 2m
几分钟后,就能看到一个外部IP自动添加到了服务上。在web浏览器里打开这个IP就可以和pod上的web服务器交互了。
Pod间通信:ClusterIP服务
我们创建一个名为mysql.yaml的新YAML文件来管理数据库:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mysql-deployment
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.6
ports:
- containerPort: 3306
# Ignore this for now. It will be explained in the next article
env:
- name: MYSQL_ALLOW_EMPTY_PASSWORD
value: "true"
---
kind: Service
apiVersion: v1
metadata:
name: mysql-service
spec:
selector:
app: mysql
ports:
- protocol: TCP
port: 3306
type: ClusterIP
大部分内容很类似。我们声明了一个Deployment来管理这个pod,通过Service管理网络连接。这里,service的类型是“ClusterIP”;这意味着这个IP仅仅暴露在集群内部,这和之前使用LoadBanlancer将Gitea服务暴露到外部不一样。
在集群里应用这个新YAML文件:
这时你可以看到集群里新加了一个Pod、Deployment和Service。$ kubectl apply -f mysql.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
gitea-pod 1/1 Running 0 9m
mysql-pod 1/1 Running 0 9s
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
gitea-deployment 1 1 1 1 11m
mysql-deployment 1 1 1 1 5m
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL_IP AGE
gitea-service LoadBalancer 10.27.240.34 35.192.x.x 2m
mysql-service ClusterIP 10.27.254.69 <none> 6m
ClusterIP服务会自动生成一个内部IP地址,显示在上面控制台输出的“CLUSTER-IP”一栏。集群内的任何容器都可以使用这一地址访问MySQL pod。但是,并不推荐直接使用内部IP地址。Kubernetes提供了更为简单的方式来访问这个新服务:可以在地址字段输入“mysql-service”即可。这是因为内建了“kube-dns[2]”Pod,它为所有服务管理内部的DNS解析。这样,用户可以忽略随机生成的内部IP地址,仅仅使用静态的,可读的服务名称就可以了。
要让Gitea能够和MySQL Pod通信,仅仅需要在Web UI的“host”字段输入服务的名称和端口就可以了。如果一切和预期一样,就会看到“access denied”的错误。这意味着Pod可以成功通信了,但是它们需要更多的配置信息才能完成认证。下一篇博客会继续介绍如何完成认证。
下一步
备注
LoadBanlancer在云服务,比如GCP上工作很好,但是如果你在Docker或者Minikube上运行本地集群,就需要使用NodePort服务代替。
外部端口可以设置成任意值,但是要记住如果你想访问非标准的东西,在GKE上需要设置防火墙规则。
这里使用MySQL因为Gitea是这么设计的。MySQL是一种遗留服务,并非Kubernetes原生的,如果你想从头开始设计应用程序,可能别的存储方案更为适合。
Kubernetes管理一些隐藏的Pod和服务。可以运行kubectl get pods --namespace=kube-system查看它们。
https://www.voxxed.com/2015/01/use-container-sidecar-microservices/
https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
https://medium.com/google-cloud/understanding-kubernetes-networking-pods-7117dd28727
https://github.com/ahmetb/kubernetes-network-policy-recipes