连接应用与 Service
Kubernetes 的容器连接模型
现在你已经有了一个持续运行的、复制的应用,你可以将其暴露到网络上。
Kubernetes 假定 Pod 可以与其他 Pod 通信,无论它们落在哪个主机上。Kubernetes 为每个 Pod 分配一个自己的集群私有 IP 地址,因此你无需显式地在 Pod 之间创建链接或将容器端口映射到主机端口。这意味着 Pod 中的容器都可以通过 localhost 访问彼此的端口,并且集群中的所有 Pod 都可以相互看到,无需 NAT。本文档的其余部分详细阐述了如何在这样的网络模型上运行可靠的 Service。
本教程使用一个简单的 nginx Web 服务器来演示这个概念。
将 Pod 暴露到集群
我们在之前的示例中做过这个,但让我们再次进行并重点关注网络方面。创建一个 nginx Pod,注意它包含容器端口的规范:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
这使得它能够从集群中的任何节点访问。检查 Pod 正在运行的节点:
kubectl apply -f ./run-my-nginx.yaml
kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
my-nginx-3800858182-jr4a2 1/1 Running 0 13s 10.244.3.4 kubernetes-minion-905m
my-nginx-3800858182-kna2y 1/1 Running 0 13s 10.244.2.5 kubernetes-minion-ljyd
检查你的 Pod IP 地址:
kubectl get pods -l run=my-nginx -o custom-columns=POD_IP:.status.podIPs
POD_IP
[map[ip:10.244.3.4]]
[map[ip:10.244.2.5]]
你应该能够 SSH 连接到集群中的任何节点,并使用 curl
等工具对这两个 IP 发起查询。请注意,容器没有使用节点上的 80 端口,也没有特殊的 NAT 规则将流量路由到 Pod。这意味着你可以在同一个节点上运行多个 nginx Pod,它们都使用相同的 containerPort
,并且可以从集群中的任何其他 Pod 或节点使用分配给该 Pod 的 IP 地址来访问它们。如果你想安排将主机节点上的特定端口转发到后端的 Pod,你可以这样做——但网络模型意味着你无需这样做。
如果你对此感兴趣,可以阅读更多关于Kubernetes 网络模型的内容。
创建 Service
因此,我们有在平坦的、集群范围的地址空间中运行 nginx 的 Pod。理论上,你可以直接与这些 Pod 通信,但当一个节点死掉时会发生什么?Pod 会随之死亡,并且 Deployment 中的 ReplicaSet 将创建新的 Pod,它们的 IP 会不同。这就是 Service 解决的问题。
Kubernetes Service 是一种抽象,它定义了在集群中某处运行的一组逻辑 Pod,这些 Pod 都提供相同的功能。创建 Service 时,会分配一个唯一的 IP 地址(也称为 clusterIP)。该地址与 Service 的生命周期绑定,在 Service 存活期间不会改变。可以将 Pod 配置为与 Service 通信,并知道与 Service 的通信将自动负载均衡到属于该 Service 的某个 Pod。
你可以使用 kubectl expose
为你的 2 个 nginx 副本创建一个 Service:
kubectl expose deployment/my-nginx
service/my-nginx exposed
这等同于对以下 YAML 文件执行 kubectl apply -f
:
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
此规范将创建一个 Service,该 Service 针对带有 run: my-nginx
标签的任何 Pod 的 TCP 端口 80,并在一个抽象的 Service 端口上暴露该端口(targetPort
:是容器接受流量的端口;port
:是抽象的 Service 端口,可以是其他 Pod 用于访问 Service 的任何端口)。查看 Service API 对象,查看 Service 定义中支持的字段列表。检查你的 Service:
kubectl get svc my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx ClusterIP 10.0.162.149 <none> 80/TCP 21s
如前所述,Service 由一组 Pod 提供支持。这些 Pod 通过EndpointSlice暴露。Service 的选择器将持续评估,结果将 POST 到使用标签连接到 Service 的 EndpointSlice。当 Pod 死亡时,它会自动从包含它的 EndpointSlice 中移除。与 Service 选择器匹配的新 Pod 将自动添加到该 Service 的 EndpointSlice。检查 Endpoints,注意它们的 IP 与第一步创建的 Pod 相同:
kubectl describe svc my-nginx
Name: my-nginx
Namespace: default
Labels: run=my-nginx
Annotations: <none>
Selector: run=my-nginx
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.0.162.149
IPs: 10.0.162.149
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.2.5:80,10.244.3.4:80
Session Affinity: None
Events: <none>
kubectl get endpointslices -l kubernetes.io/service-name=my-nginx
NAME ADDRESSTYPE PORTS ENDPOINTS AGE
my-nginx-7vzhx IPv4 80 10.244.2.5,10.244.3.4 21s
现在你应该能够从集群中的任何节点使用 curl
访问 nginx Service 的 <CLUSTER-IP>:<PORT>
。请注意,Service IP 完全是虚拟的,它永远不会出现在物理网络上。如果你对它的工作原理感到好奇,可以阅读更多关于Service 代理的内容。
访问 Service
Kubernetes 支持两种主要的 Service 发现模式:环境变量和 DNS。前者开箱即用,而后者需要安装 CoreDNS 集群插件。
注意
如果不想使用 Service 环境变量(例如可能与程序预期的环境变量冲突、需要处理的变量过多、仅使用 DNS 等),你可以在 Pod 规约中将enableServiceLinks
标志设置为 false
来禁用此模式。环境变量
当 Pod 运行在节点上时,kubelet 会为每个活动的 Service 添加一组环境变量。这引入了排序问题。要了解原因,请检查正在运行的 nginx Pod 的环境变量(你的 Pod 名称可能会不同):
kubectl exec my-nginx-3800858182-jr4a2 -- printenv | grep SERVICE
KUBERNETES_SERVICE_HOST=10.0.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
请注意,其中没有提到你的 Service。这是因为你在创建 Service 之前就创建了副本。这样做还有另一个缺点,调度器可能会将两个 Pod 放在同一台机器上,如果机器死掉,你的整个 Service 都会随之宕机。我们可以通过杀死这两个 Pod 并等待 Deployment 重新创建它们来正确地做到这一点。这次 Service 在副本创建之前就已存在。这将为你提供调度器级别的 Pod Service 分散(前提是所有节点具有相同的容量),以及正确的环境变量:
kubectl scale deployment my-nginx --replicas=0; kubectl scale deployment my-nginx --replicas=2;
kubectl get pods -l run=my-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
my-nginx-3800858182-e9ihh 1/1 Running 0 5s 10.244.2.7 kubernetes-minion-ljyd
my-nginx-3800858182-j4rm4 1/1 Running 0 5s 10.244.3.8 kubernetes-minion-905m
你可能会注意到 Pod 的名称不同,因为它们被杀死并重新创建了。
kubectl exec my-nginx-3800858182-e9ihh -- printenv | grep SERVICE
KUBERNETES_SERVICE_PORT=443
MY_NGINX_SERVICE_HOST=10.0.162.149
KUBERNETES_SERVICE_HOST=10.0.0.1
MY_NGINX_SERVICE_PORT=80
KUBERNETES_SERVICE_PORT_HTTPS=443
DNS
Kubernetes 提供了一个 DNS 集群插件 Service,它会自动为其他 Service 分配 DNS 名称。你可以检查它是否在你的集群中运行:
kubectl get services kube-dns --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.0.0.10 <none> 53/UDP,53/TCP 8m
本节的其余部分将假设你有一个具有长生命周期 IP 的 Service (my-nginx),并且有一个 DNS 服务器为该 IP 分配了名称。这里我们使用 CoreDNS 集群插件(应用名称 kube-dns
),因此你可以从集群中的任何 Pod 使用标准方法(例如 gethostbyname()
)与 Service 通信。如果 CoreDNS 没有运行,你可以参考 CoreDNS README 或 安装 CoreDNS 来启用它。让我们运行另一个 curl 应用来测试:
kubectl run curl --image=radial/busyboxplus:curl -i --tty --rm
Waiting for pod default/curl-131556218-9fnch to be running, status is Pending, pod ready: false
Hit enter for command prompt
然后,按回车键并运行 nslookup my-nginx
:
[ root@curl-131556218-9fnch:/ ]$ nslookup my-nginx
Server: 10.0.0.10
Address 1: 10.0.0.10
Name: my-nginx
Address 1: 10.0.162.149
保护 Service
到目前为止,我们只从集群内部访问了 nginx 服务器。在将 Service 暴露到互联网之前,你需要确保通信通道是安全的。为此,你需要:
- 用于 HTTPS 的自签名证书(除非你已有身份证书)
- 配置为使用证书的 nginx 服务器
- 一个使证书对 Pod 可访问的 Secret
你可以从 nginx https 示例中获取所有这些。这需要安装 go 和 make 工具。如果你不想安装它们,请稍后按照手动步骤操作。简而言之:
make keys KEY=/tmp/nginx.key CERT=/tmp/nginx.crt
kubectl create secret tls nginxsecret --key /tmp/nginx.key --cert /tmp/nginx.crt
secret/nginxsecret created
kubectl get secrets
NAME TYPE DATA AGE
nginxsecret kubernetes.io/tls 2 1m
以及 ConfigMap:
kubectl create configmap nginxconfigmap --from-file=default.conf
你可以在 Kubernetes 示例项目仓库中找到 default.conf
的示例。
configmap/nginxconfigmap created
kubectl get configmaps
NAME DATA AGE
nginxconfigmap 1 114s
你可以使用以下命令查看 nginxconfigmap
ConfigMap 的详细信息:
kubectl describe configmap nginxconfigmap
输出类似于:
Name: nginxconfigmap
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
default.conf:
----
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
listen 443 ssl;
root /usr/share/nginx/html;
index index.html;
server_name localhost;
ssl_certificate /etc/nginx/ssl/tls.crt;
ssl_certificate_key /etc/nginx/ssl/tls.key;
location / {
try_files $uri $uri/ =404;
}
}
BinaryData
====
Events: <none>
如果你在运行 make 时遇到问题(例如在 Windows 上),以下是手动操作步骤:
# Create a public private key pair
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /d/tmp/nginx.key -out /d/tmp/nginx.crt -subj "/CN=my-nginx/O=my-nginx"
# Convert the keys to base64 encoding
cat /d/tmp/nginx.crt | base64
cat /d/tmp/nginx.key | base64
使用之前命令的输出按如下方式创建一个 YAML 文件。base64 编码的值应该都在一行上。
apiVersion: "v1"
kind: "Secret"
metadata:
name: "nginxsecret"
namespace: "default"
type: kubernetes.io/tls
data:
tls.crt: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURIekNDQWdlZ0F3SUJBZ0lKQUp5M3lQK0pzMlpJTUEwR0NTcUdTSWIzRFFFQkJRVUFNQ1l4RVRBUEJnTlYKQkFNVENHNW5hVzU0YzNaak1SRXdEd1lEVlFRS0V3aHVaMmx1ZUhOMll6QWVGdzB4TnpFd01qWXdOekEzTVRKYQpGdzB4T0RFd01qWXdOekEzTVRKYU1DWXhFVEFQQmdOVkJBTVRDRzVuYVc1NGMzWmpNUkV3RHdZRFZRUUtFd2h1CloybHVlSE4yWXpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSjFxSU1SOVdWM0IKMlZIQlRMRmtobDRONXljMEJxYUhIQktMSnJMcy8vdzZhU3hRS29GbHlJSU94NGUrMlN5ajBFcndCLzlYTnBwbQppeW1CL3JkRldkOXg5UWhBQUxCZkVaTmNiV3NsTVFVcnhBZW50VWt1dk1vLzgvMHRpbGhjc3paenJEYVJ4NEo5Ci82UVRtVVI3a0ZTWUpOWTVQZkR3cGc3dlVvaDZmZ1Voam92VG42eHNVR0M2QURVODBpNXFlZWhNeVI1N2lmU2YKNHZpaXdIY3hnL3lZR1JBRS9mRTRqakxCdmdONjc2SU90S01rZXV3R0ljNDFhd05tNnNTSzRqYUNGeGpYSnZaZQp2by9kTlEybHhHWCtKT2l3SEhXbXNhdGp4WTRaNVk3R1ZoK0QrWnYvcW1mMFgvbVY0Rmo1NzV3ajFMWVBocWtsCmdhSXZYRyt4U1FVQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjcKTUI4R0ExVWRJd1FZTUJhQUZPNG9OWkI3YXc1OUlsYkROMzhIYkduYnhFVjdNQXdHQTFVZEV3UUZNQU1CQWY4dwpEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRVhTMW9FU0lFaXdyMDhWcVA0K2NwTHI3TW5FMTducDBvMm14alFvCjRGb0RvRjdRZnZqeE04Tzd2TjB0clcxb2pGSW0vWDE4ZnZaL3k4ZzVaWG40Vm8zc3hKVmRBcStNZC9jTStzUGEKNmJjTkNUekZqeFpUV0UrKzE5NS9zb2dmOUZ3VDVDK3U2Q3B5N0M3MTZvUXRUakViV05VdEt4cXI0Nk1OZWNCMApwRFhWZmdWQTRadkR4NFo3S2RiZDY5eXM3OVFHYmg5ZW1PZ05NZFlsSUswSGt0ejF5WU4vbVpmK3FqTkJqbWZjCkNnMnlwbGQ0Wi8rUUNQZjl3SkoybFIrY2FnT0R4elBWcGxNSEcybzgvTHFDdnh6elZPUDUxeXdLZEtxaUMwSVEKQ0I5T2wwWW5scE9UNEh1b2hSUzBPOStlMm9KdFZsNUIyczRpbDlhZ3RTVXFxUlU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
tls.key: "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQ2RhaURFZlZsZHdkbFIKd1V5eFpJWmVEZWNuTkFhbWh4d1NpeWF5N1AvOE9ta3NVQ3FCWmNpQ0RzZUh2dGtzbzlCSzhBZi9WemFhWm9zcApnZjYzUlZuZmNmVUlRQUN3WHhHVFhHMXJKVEVGSzhRSHA3VkpMcnpLUC9QOUxZcFlYTE0yYzZ3MmtjZUNmZitrCkU1bEVlNUJVbUNUV09UM3c4S1lPNzFLSWVuNEZJWTZMMDUrc2JGQmd1Z0ExUE5JdWFubm9UTWtlZTRuMG4rTDQKb3NCM01ZUDhtQmtRQlAzeE9JNHl3YjREZXUraURyU2pKSHJzQmlIT05Xc0RadXJFaXVJMmdoY1kxeWIyWHI2UAozVFVOcGNSbC9pVG9zQngxcHJHclk4V09HZVdPeGxZZmcvbWIvNnBuOUYvNWxlQlkrZStjSTlTMkQ0YXBKWUdpCkwxeHZzVWtGQWdNQkFBRUNnZ0VBZFhCK0xkbk8ySElOTGo5bWRsb25IUGlHWWVzZ294RGQwci9hQ1Zkank4dlEKTjIwL3FQWkUxek1yall6Ry9kVGhTMmMwc0QxaTBXSjdwR1lGb0xtdXlWTjltY0FXUTM5SjM0VHZaU2FFSWZWNgo5TE1jUHhNTmFsNjRLMFRVbUFQZytGam9QSFlhUUxLOERLOUtnNXNrSE5pOWNzMlY5ckd6VWlVZWtBL0RBUlBTClI3L2ZjUFBacDRuRWVBZmI3WTk1R1llb1p5V21SU3VKdlNyblBESGtUdW1vVlVWdkxMRHRzaG9reUxiTWVtN3oKMmJzVmpwSW1GTHJqbGtmQXlpNHg0WjJrV3YyMFRrdWtsZU1jaVlMbjk4QWxiRi9DSmRLM3QraTRoMTVlR2ZQegpoTnh3bk9QdlVTaDR2Q0o3c2Q5TmtEUGJvS2JneVVHOXBYamZhRGR2UVFLQmdRRFFLM01nUkhkQ1pKNVFqZWFKClFGdXF4cHdnNzhZTjQyL1NwenlUYmtGcVFoQWtyczJxWGx1MDZBRzhrZzIzQkswaHkzaE9zSGgxcXRVK3NHZVAKOWRERHBsUWV0ODZsY2FlR3hoc0V0L1R6cEdtNGFKSm5oNzVVaTVGZk9QTDhPTm1FZ3MxMVRhUldhNzZxelRyMgphRlpjQ2pWV1g0YnRSTHVwSkgrMjZnY0FhUUtCZ1FEQmxVSUUzTnNVOFBBZEYvL25sQVB5VWs1T3lDdWc3dmVyClUycXlrdXFzYnBkSi9hODViT1JhM05IVmpVM25uRGpHVHBWaE9JeXg5TEFrc2RwZEFjVmxvcG9HODhXYk9lMTAKMUdqbnkySmdDK3JVWUZiRGtpUGx1K09IYnRnOXFYcGJMSHBzUVpsMGhucDBYSFNYVm9CMUliQndnMGEyOFVadApCbFBtWmc2d1BRS0JnRHVIUVV2SDZHYTNDVUsxNFdmOFhIcFFnMU16M2VvWTBPQm5iSDRvZUZKZmcraEppSXlnCm9RN3hqWldVR3BIc3AyblRtcHErQWlSNzdyRVhsdlhtOElVU2FsbkNiRGlKY01Pc29RdFBZNS9NczJMRm5LQTQKaENmL0pWb2FtZm1nZEN0ZGtFMXNINE9MR2lJVHdEbTRpb0dWZGIwMllnbzFyb2htNUpLMUI3MkpBb0dBUW01UQpHNDhXOTVhL0w1eSt5dCsyZ3YvUHM2VnBvMjZlTzRNQ3lJazJVem9ZWE9IYnNkODJkaC8xT2sybGdHZlI2K3VuCnc1YytZUXRSTHlhQmd3MUtpbGhFZDBKTWU3cGpUSVpnQWJ0LzVPbnlDak9OVXN2aDJjS2lrQ1Z2dTZsZlBjNkQKckliT2ZIaHhxV0RZK2Q1TGN1YSt2NzJ0RkxhenJsSlBsRzlOZHhrQ2dZRUF5elIzT3UyMDNRVVV6bUlCRkwzZAp4Wm5XZ0JLSEo3TnNxcGFWb2RjL0d5aGVycjFDZzE2MmJaSjJDV2RsZkI0VEdtUjZZdmxTZEFOOFRwUWhFbUtKCnFBLzVzdHdxNWd0WGVLOVJmMWxXK29xNThRNTBxMmk1NVdUTThoSDZhTjlaMTltZ0FGdE5VdGNqQUx2dFYxdEYKWSs4WFJkSHJaRnBIWll2NWkwVW1VbGc9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K"
现在使用该文件创建 Secret:
kubectl apply -f nginxsecrets.yaml
kubectl get secrets
NAME TYPE DATA AGE
nginxsecret kubernetes.io/tls 2 1m
现在修改你的 nginx 副本,使用 Secret 中的证书启动一个 HTTPS 服务器,并使用 Service 暴露两个端口(80 和 443):
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
type: NodePort
ports:
- port: 8080
targetPort: 80
protocol: TCP
name: http
- port: 443
protocol: TCP
name: https
selector:
run: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
volumes:
- name: secret-volume
secret:
secretName: nginxsecret
- name: configmap-volume
configMap:
name: nginxconfigmap
containers:
- name: nginxhttps
image: bprashanth/nginxhttps:1.0
ports:
- containerPort: 443
- containerPort: 80
volumeMounts:
- mountPath: /etc/nginx/ssl
name: secret-volume
- mountPath: /etc/nginx/conf.d
name: configmap-volume
关于 nginx-secure-app 清单的值得注意的点:
- 它在同一个文件中包含 Deployment 和 Service 规范。
- nginx 服务器在端口 80 提供 HTTP 流量服务,在端口 443 提供 HTTPS 流量服务,并且 nginx Service 暴露了这两个端口。
- 每个容器通过挂载到
/etc/nginx/ssl
的卷访问密钥。这是在 nginx 服务器启动之前设置好的。
kubectl delete deployments,svc my-nginx; kubectl create -f ./nginx-secure-app.yaml
此时,你可以从任何节点访问 nginx 服务器。
kubectl get pods -l run=my-nginx -o custom-columns=POD_IP:.status.podIPs
POD_IP
[map[ip:10.244.3.5]]
node $ curl -k https://10.244.3.5
...
<h1>Welcome to nginx!</h1>
注意我们在上一步如何给 curl 提供了 -k
参数,这是因为我们在生成证书时不知道运行 nginx 的 Pod 的任何信息,所以我们必须告诉 curl 忽略 CName 不匹配。通过创建 Service,我们将证书中使用的 CName 与 Pod 在 Service 查找期间使用的实际 DNS 名称关联起来。让我们从一个 Pod 中测试(为简单起见,重复使用相同的 Secret,Pod 只需 nginx.crt 即可访问 Service):
apiVersion: apps/v1
kind: Deployment
metadata:
name: curl-deployment
spec:
selector:
matchLabels:
app: curlpod
replicas: 1
template:
metadata:
labels:
app: curlpod
spec:
volumes:
- name: secret-volume
secret:
secretName: nginxsecret
containers:
- name: curlpod
command:
- sh
- -c
- while true; do sleep 1; done
image: radial/busyboxplus:curl
volumeMounts:
- mountPath: /etc/nginx/ssl
name: secret-volume
kubectl apply -f ./curlpod.yaml
kubectl get pods -l app=curlpod
NAME READY STATUS RESTARTS AGE
curl-deployment-1515033274-1410r 1/1 Running 0 1m
kubectl exec curl-deployment-1515033274-1410r -- curl https://my-nginx --cacert /etc/nginx/ssl/tls.crt
...
<title>Welcome to nginx!</title>
...
暴露 Service
对于应用程序的某些部分,你可能希望将 Service 暴露到外部 IP 地址。Kubernetes 支持两种方法:NodePort 和 LoadBalancer。上一节创建的 Service 已经使用了 NodePort
,所以如果你的节点有公共 IP,你的 nginx HTTPS 副本就可以在互联网上提供流量服务。
kubectl get svc my-nginx -o yaml | grep nodePort -C 5
uid: 07191fb3-f61a-11e5-8ae5-42010af00002
spec:
clusterIP: 10.0.162.149
ports:
- name: http
nodePort: 31704
port: 8080
protocol: TCP
targetPort: 80
- name: https
nodePort: 32453
port: 443
protocol: TCP
targetPort: 443
selector:
run: my-nginx
kubectl get nodes -o yaml | grep ExternalIP -C 1
- address: 104.197.41.11
type: ExternalIP
allocatable:
--
- address: 23.251.152.56
type: ExternalIP
allocatable:
...
$ curl https://<EXTERNAL-IP>:<NODE-PORT> -k
...
<h1>Welcome to nginx!</h1>
现在我们重新创建 Service 以使用云负载均衡器。将 my-nginx
Service 的 Type
从 NodePort
更改为 LoadBalancer
:
kubectl edit svc my-nginx
kubectl get svc my-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx LoadBalancer 10.0.162.149 xx.xxx.xxx.xxx 8080:30163/TCP 21s
curl https://<EXTERNAL-IP> -k
...
<title>Welcome to nginx!</title>
EXTERNAL-IP
列中的 IP 地址是在公共互联网上可用的地址。CLUSTER-IP
仅在你的集群/私有云网络内部可用。
请注意,在 AWS 上,类型为 LoadBalancer
会创建一个 ELB,它使用(很长的)主机名而不是 IP。实际上,它太长了,无法适应标准的 kubectl get svc
输出,因此你需要执行 kubectl describe service my-nginx
才能看到它。你会看到类似如下的内容:
kubectl describe service my-nginx
...
LoadBalancer Ingress: a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.elb.amazonaws.com
...
接下来
- 了解更多关于使用 Service 访问集群中的应用的信息。
- 了解更多关于使用 Service 连接前端和后端的信息。
- 了解更多关于创建外部负载均衡器的信息。