使用服务连接应用程序
Kubernetes 连接容器的模型
现在您已经拥有了一个持续运行的复制应用程序,您可以将其暴露在网络上。
Kubernetes 假设 Pod 可以相互通信,无论它们位于哪个主机上。Kubernetes 为每个 Pod 提供其自己的集群私有 IP 地址,因此您无需显式创建 Pod 之间的链接或将容器端口映射到主机端口。这意味着 Pod 内的容器都可以通过 localhost 访问彼此的端口,并且集群中的所有 Pod 都可以互相看到,而无需 NAT。本文档的其余部分将详细说明如何在这样的网络模型上运行可靠的服务。
本教程使用一个简单的 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 的 IP 地址从集群中的任何其他 Pod 或节点访问它们。如果您想安排主机节点上的特定端口转发到后端 Pod,您可以这样做 - 但网络模型应该意味着您无需这样做。
如果您好奇,可以阅读有关Kubernetes 网络模型的更多信息。
创建服务
因此,我们在一个扁平的、集群范围的地址空间中运行着 nginx Pod。理论上,您可以直接与这些 Pod 交谈,但如果节点死机怎么办?Pod 会随之死机,Deployment 中的 ReplicaSet 会创建新的 Pod,它们具有不同的 IP。这就是服务解决的问题。
Kubernetes 服务是一种抽象,它定义了集群中某个地方运行的一组逻辑 Pod,它们都提供相同的功能。创建时,每个服务都会分配一个唯一的 IP 地址(也称为 clusterIP)。此地址与服务的生命周期绑定,并且在服务处于活动状态时不会更改。可以配置 Pod 与服务进行通信,并知道与服务的通信将自动负载均衡到作为服务成员的某个 Pod。
您可以使用 kubectl expose
为 2 个 nginx 副本创建服务
kubectl expose deployment/my-nginx
service/my-nginx exposed
这等效于 kubectl apply -f
以下 yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
此规范将创建一个服务,该服务将针对具有 run: my-nginx
标签的任何 Pod 上的 TCP 端口 80,并在抽象的服务端口上公开它(targetPort
:是容器接受流量的端口,port
:是抽象的服务端口,可以是任何其他 Pod 用于访问服务的端口)。查看服务 API 对象以查看服务定义中支持的字段列表。检查您的服务
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
如前所述,服务由一组 Pod 支持。这些 Pod 通过EndpointSlices公开。服务的 selector 将持续评估,结果将被 POST 到一个 EndpointSlice,该 EndpointSlice 使用标签连接到服务。当 Pod 死机时,它会自动从包含它作为端点的 EndpointSlices 中删除。匹配服务 selector 的新 Pod 将自动添加到该服务的 EndpointSlice 中。检查端点,并注意 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
您现在应该能够从集群中的任何节点使用 <CLUSTER-IP>:<PORT>
对 nginx 服务进行 curl。请注意,服务 IP 完全是虚拟的,它永远不会到达网络。如果您好奇它是如何工作的,您可以阅读有关服务代理的更多信息。
访问服务
Kubernetes 支持两种主要的服务查找模式 - 环境变量和 DNS。前者开箱即用,而后者需要CoreDNS 集群插件。
注意
如果不需要服务环境变量(因为可能与预期的程序变量冲突、处理的变量太多、只使用 DNS 等等),您可以通过在Pod 规范上将enableServiceLinks
标志设置为 false
来禁用此模式。环境变量
当 Pod 在节点上运行时,kubelet 会为每个活动服务添加一组环境变量。这引入了排序问题。要了解原因,请检查正在运行的 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
请注意,没有提到您的服务。这是因为您在服务之前创建了副本。这样做的另一个缺点是,调度程序可能会将两个 Pod 放在同一台机器上,如果它死机,这将使您的整个服务停止运行。我们可以通过杀死这两个 Pod 并等待 Deployment 重新创建它们来正确地执行此操作。这次,服务在副本之前存在。这将为您提供调度程序级别的服务传播(前提是所有节点的容量都相同),以及正确的环境变量
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 集群插件服务,该服务会自动为其他服务分配 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(my-nginx)的服务,以及一个已为该 IP 分配名称的 DNS 服务器。这里我们使用 CoreDNS 集群插件(应用程序名称 kube-dns
),因此您可以使用标准方法(例如 gethostbyname()
)从集群中的任何 Pod 与服务进行通信。如果 CoreDNS 未运行,您可以参考CoreDNS 自述文件或安装 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
保护服务
到目前为止,我们只从集群内部访问了 nginx 服务器。在将服务暴露给互联网之前,您需要确保通信通道是安全的。为此,您将需要
- 用于 https 的自签名证书(除非您已经拥有身份证书)
- 配置为使用证书的 nginx 服务器
- 一个秘密,使证书可供 Pod 访问
您可以从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"
现在使用该文件创建秘密
kubectl apply -f nginxsecrets.yaml
kubectl get secrets
NAME TYPE DATA AGE
nginxsecret kubernetes.io/tls 2 1m
现在修改您的 nginx 副本以使用秘密中的证书启动 https 服务器,以及服务,以公开两个端口(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 清单的值得注意的要点
- 该文件包含部署和服务规范。
- 该 nginx 服务器 在端口 80 上提供 HTTP 流量,在端口 443 上提供 HTTPS 流量,nginx 服务公开这两个端口。
- 每个容器都可以通过挂载在
/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 不匹配。通过创建服务,我们将证书中使用的 CName 与 pod 在服务查找期间使用的实际 DNS 名称链接起来。让我们从 pod 中测试一下(为了简单起见,同一个密钥被重复使用,pod 只需要 nginx.crt 来访问服务)
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>
...
公开服务
对于应用程序的某些部分,您可能希望将服务公开到外部 IP 地址。Kubernetes 支持两种方法:NodePorts 和 LoadBalancers。上一节中创建的服务已经使用了 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>
现在让我们重新创建服务以使用云负载均衡器。将 my-nginx
服务的 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
...
下一步
- 了解有关 使用服务访问集群中的应用程序 的更多信息
- 了解有关 使用服务将前端连接到后端 的更多信息
- 了解有关 创建外部负载均衡器 的更多信息