为什么我的 pod 不响应公开端口上的请求?
Why doesn't my pod respond to requests on the exposed port?
我刚刚启动了一个基于 CoreOS kube-aws 脚本的相当基本的集群。
https://coreos.com/kubernetes/docs/latest/kubernetes-on-aws.html
我已经激活了 registry 插件,并且我已经正确地代理了我的本地盒子,所以我可以将图像推送到 localhost:5000 上的集群。我还在每个节点上正确加载了代理 pod,这样 localhost:5000 也将从该注册表中提取图像。
https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/registry
然后我将一个相当简单的 Sinatra 应用程序停靠到我的集群上的 运行,并将其推送到注册表。我还为 运行 应用程序准备了 ReplicationController 定义和服务定义。镜像拉取并启动没有问题,我可以使用 kubectl
从属于复制组的每个 pod 获取启动日志。
我的问题是,当我 curl
我的服务的 public ELB 端点时,它只是挂起。
我尝试过的事情:
- 我得到了 public 我的 pod 中一个节点的 public IP,并尝试
curl
在服务描述中描述的 NodePort 上 curl
它,同样的事情。
- 我通过 SSH 连接到该节点并尝试
curl localhost:3000
,结果相同。
- 我也通过 SSH 连接到该节点,我尝试
curl <pod-ip>:3000
,结果相同。
ps
显示 Puma 进程 运行正在侦听端口 3000。
节点上的 docker ps
显示应用程序容器未将任何端口转发到主机。这可能是问题所在吗?
请求必须正确路由,因为在任何其他端口访问这些 IP 会导致 connection refused
而不是挂起。
我的应用程序的 Dockerfile 相当简单:
FROM ruby:2.2.4-onbuild
RUN apt-get update -qq && apt-get install -y \
libpq-dev \
postgresql-client
RUN mkdir -p /app
WORKDIR /app
COPY . /app
EXPOSE 3000
ENTRYPOINT ['ruby', '/app/bin/entrypoint.rb']
其中 entrypoint.rb
将启动一个监听端口 3000 的 Puma 服务器。
我的复制组是这样定义的:
apiVersion: v1
kind: ReplicationController
metadata:
name: web-controller
namespace: app
spec:
replicas: 2
selector:
app: web
template:
metadata:
labels:
app: web
spec:
volumes:
- name: secrets
secret:
secretName: secrets
containers:
- name: app
image: localhost:5000/app:v2
resources:
limits:
cpu: 100m
memory: 50Mi
env:
- name: DATABASE_NAME
value: app_production
- name: DATABASE_URL
value: postgresql://some.postgres.aws.com:5432
- name: ENV
value: production
- name: REDIS_URL
value: redis://some.redis.aws.com:6379
volumeMounts:
- name: secrets
mountPath: "/etc/secrets"
readOnly: true
command: ['/app/bin/entrypoint.rb', 'web']
ports:
- containerPort: 3000
这是我的服务:
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
ports:
- port: 80
targetPort: 3000
protocol: TCP
selector:
app: web
type: LoadBalancer
kubectl describe service web-service
的输出:
Name: web-service
Namespace: app
Labels: <none>
Selector: app=web
Type: LoadBalancer
IP: 10.3.0.204
LoadBalancer Ingress: some.elb.aws.com
Port: <unnamed> 80/TCP
NodePort: <unnamed> 32062/TCP
Endpoints: 10.2.47.3:3000,10.2.73.3:3000
Session Affinity: None
No events.
其中一个节点上的 docker ps
显示应用程序容器未将任何端口转发到主机。这可能是问题所在吗?
编辑以添加 entrypoint.rb 和 Procfile
entrypoint.rb:
#!/usr/bin/env ruby
db_user_file = '/etc/secrets/database_user'
db_password_file = '/etc/secrets/database_password'
ENV['DATABASE_USER'] = File.read(db_user_file) if File.exists?(db_user_file)
ENV['DATABASE_PASSWORD'] = File.read(db_password_file) if File.exists?(db_password_file)
exec("bundle exec foreman start #{ARGV[0]}")
过程文件:
web: PORT=3000 bundle exec puma
message_worker: bundle exec sidekiq -q messages -c 1 -r ./config/environment.rb
email_worker: bundle exec sidekiq -q emails -c 1 -r
我的 Kubernetes 设置没有任何问题。事实证明,应用程序无法启动是因为与数据库的连接由于一些不相关的网络问题而超时。
对于任何好奇的人:不要在 10.x.x.x IP 范围内启动 Kubernetes 外部的任何东西(例如 RDS、Elasticache 等)。长话短说,Kubernetes 目前有一个硬编码的 IPTables 伪装规则,它会扰乱与该范围内不属于集群的任何东西的通信。查看详情 here.
我最终做的是在不同的 IP 范围内为我的数据存储创建一个单独的 VPC,并将其与我的 Kubernetes VPC 对等。
我刚刚启动了一个基于 CoreOS kube-aws 脚本的相当基本的集群。
https://coreos.com/kubernetes/docs/latest/kubernetes-on-aws.html
我已经激活了 registry 插件,并且我已经正确地代理了我的本地盒子,所以我可以将图像推送到 localhost:5000 上的集群。我还在每个节点上正确加载了代理 pod,这样 localhost:5000 也将从该注册表中提取图像。
https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/registry
然后我将一个相当简单的 Sinatra 应用程序停靠到我的集群上的 运行,并将其推送到注册表。我还为 运行 应用程序准备了 ReplicationController 定义和服务定义。镜像拉取并启动没有问题,我可以使用 kubectl
从属于复制组的每个 pod 获取启动日志。
我的问题是,当我 curl
我的服务的 public ELB 端点时,它只是挂起。
我尝试过的事情:
- 我得到了 public 我的 pod 中一个节点的 public IP,并尝试
curl
在服务描述中描述的 NodePort 上curl
它,同样的事情。 - 我通过 SSH 连接到该节点并尝试
curl localhost:3000
,结果相同。 - 我也通过 SSH 连接到该节点,我尝试
curl <pod-ip>:3000
,结果相同。 ps
显示 Puma 进程 运行正在侦听端口 3000。
节点上的 docker ps
显示应用程序容器未将任何端口转发到主机。这可能是问题所在吗?
请求必须正确路由,因为在任何其他端口访问这些 IP 会导致 connection refused
而不是挂起。
我的应用程序的 Dockerfile 相当简单:
FROM ruby:2.2.4-onbuild
RUN apt-get update -qq && apt-get install -y \
libpq-dev \
postgresql-client
RUN mkdir -p /app
WORKDIR /app
COPY . /app
EXPOSE 3000
ENTRYPOINT ['ruby', '/app/bin/entrypoint.rb']
其中 entrypoint.rb
将启动一个监听端口 3000 的 Puma 服务器。
我的复制组是这样定义的:
apiVersion: v1
kind: ReplicationController
metadata:
name: web-controller
namespace: app
spec:
replicas: 2
selector:
app: web
template:
metadata:
labels:
app: web
spec:
volumes:
- name: secrets
secret:
secretName: secrets
containers:
- name: app
image: localhost:5000/app:v2
resources:
limits:
cpu: 100m
memory: 50Mi
env:
- name: DATABASE_NAME
value: app_production
- name: DATABASE_URL
value: postgresql://some.postgres.aws.com:5432
- name: ENV
value: production
- name: REDIS_URL
value: redis://some.redis.aws.com:6379
volumeMounts:
- name: secrets
mountPath: "/etc/secrets"
readOnly: true
command: ['/app/bin/entrypoint.rb', 'web']
ports:
- containerPort: 3000
这是我的服务:
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
ports:
- port: 80
targetPort: 3000
protocol: TCP
selector:
app: web
type: LoadBalancer
kubectl describe service web-service
的输出:
Name: web-service
Namespace: app
Labels: <none>
Selector: app=web
Type: LoadBalancer
IP: 10.3.0.204
LoadBalancer Ingress: some.elb.aws.com
Port: <unnamed> 80/TCP
NodePort: <unnamed> 32062/TCP
Endpoints: 10.2.47.3:3000,10.2.73.3:3000
Session Affinity: None
No events.
其中一个节点上的 docker ps
显示应用程序容器未将任何端口转发到主机。这可能是问题所在吗?
编辑以添加 entrypoint.rb 和 Procfile
entrypoint.rb:
#!/usr/bin/env ruby
db_user_file = '/etc/secrets/database_user'
db_password_file = '/etc/secrets/database_password'
ENV['DATABASE_USER'] = File.read(db_user_file) if File.exists?(db_user_file)
ENV['DATABASE_PASSWORD'] = File.read(db_password_file) if File.exists?(db_password_file)
exec("bundle exec foreman start #{ARGV[0]}")
过程文件:
web: PORT=3000 bundle exec puma
message_worker: bundle exec sidekiq -q messages -c 1 -r ./config/environment.rb
email_worker: bundle exec sidekiq -q emails -c 1 -r
我的 Kubernetes 设置没有任何问题。事实证明,应用程序无法启动是因为与数据库的连接由于一些不相关的网络问题而超时。
对于任何好奇的人:不要在 10.x.x.x IP 范围内启动 Kubernetes 外部的任何东西(例如 RDS、Elasticache 等)。长话短说,Kubernetes 目前有一个硬编码的 IPTables 伪装规则,它会扰乱与该范围内不属于集群的任何东西的通信。查看详情 here.
我最终做的是在不同的 IP 范围内为我的数据存储创建一个单独的 VPC,并将其与我的 Kubernetes VPC 对等。