У меня есть кластер k3s (облегченный k8s), работающий на моем Raspberry PI. Итак, я использую не какой-либо облачный кластер, а медвежий металл на моем Raspberry PI.
Я развернул приложение с этим манифестом:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
namespace: myapp
spec:
replicas: 3
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: bashofmann/rancher-demo:1.0.0
imagePullPolicy: Always
resources:
requests:
cpu: 200m
ports:
- containerPort: 8080
name: web
protocol: TCP
Я также создал службу для перенаправления трафика в модуль приложения. Его манифест:
apiVersion: v1
kind: Service
metadata:
name: demo-app-svc
namespace: myapp
spec:
selector:
app: hello-world
ports:
- name: web
protocol: TCP
port: 31113
targetPort: 8080
Затем я создал Ingress для правил маршрутизации:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ing
namespace: myapp
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: myapp.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: demo-app-svc
port:
number: 31113
Я успешно развернул вышеупомянутый модуль приложения, сервис и Ingress в своем кластере k3s. Как указано в манифестах, они находятся в пространстве имен myapp
.
Следующее, что я хотел бы сделать, — это развернуть Kubernetes Nginx Ingress Controller, чтобы клиенты вне кластера могли получить доступ к развернутому приложению.
Итак, я развернул его:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml
Приведенная выше команда успешно развернула Ingress Controller в пространстве имен ingress-nginx
вместе с другими объектами, как показано ниже с помощью команды k get all -n ingress-nginx
:
Как вы можете видеть выше, внешний IP-адрес типа LoadBalancer
имеет значение service
. Таким образом, клиент вне кластера по-прежнему не может получить доступ к модулю приложения.
Почему это так и что мне не хватает при развертывании Nginx Ingress Controller на машине медвежьего металла? Цель состоит в том, чтобы иметь внешний IP-адрес, который можно использовать для доступа к пакету приложений из внешнего кластера, как я могу этого добиться?
===== Обновление =====
Основываясь на приведенном ниже ответе @David Kruk, я решил использовать контроллер Traefik Ingress по умолчанию k3s.
Итак, я удалил все развернутые ресурсы Nginx Ingress Controller с помощью <pending>
.
Затем я проверил сервис типа k delete all --all -n ingress-nginx
, связанный с Traefik Ingress:
LoadBalancer
этого сервиса Traefik — это именно IP-адрес моего Raspberry PI!
Итак, я добавил этот IP-адрес в external IP
, чтобы сопоставить его с именем хоста, определенным в моем объекте Ingress:
192.168.10.203 myapp.com
Я открыл браузер и использовал адрес http://myapp.com с правилами маршрутизации, определенными в моем объекте /etc/hosts
(см. манифест для моего входа выше), я надеялся, что теперь смогу увидеть развернутое веб-приложение. Но получайте Ingress
. Чего мне сейчас не хватает для доступа к моему развернутому приложению?
Еще один побочный вопрос: я заметил, что когда я проверяю развернутый объект 404 Page Not Found
, его IP-адрес пуст, интересно, должен ли я видеть IP-адрес для этого объекта или нет, когда Traefik Ingress Controller вступает в силу?
Еще одна проблема: теперь, когда я повторно развертываю свой входной манифест с помощью Ingress
, я получаю сообщение об ошибке:
Resource: "networking.k8s.io/v1, Resource=ingresses", GroupVersionKind: "networking.k8s.io/v1, Kind=Ingress"
...
for: "ingress.yaml": error when patching "ingress.yaml": Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": failed to call webhook: Post "https://ingress-nginx-controller-admission.ingress-nginx.svc:443/networking/v1/ingresses?timeout=10s": service "ingress-nginx-controller-admission" not found
Похоже, даже я решил использовать Traefik Ingress Controller, мне все равно нужно установить Nginx Ingress Controller. Я запутался сейчас, кто-нибудь может объяснить это?
Я не эксперт по K3S, но мне кажется, что я нашел документацию, посвященную вашей проблеме.
Взглянем:
Балансировщик нагрузки службы
В вашем кластере K3s можно использовать любой балансировщик нагрузки службы (LB). По умолчанию K3s предоставляет балансировщик нагрузки, известный как ServiceLB (ранее Klipper Load Balancer), который использует доступные хост-порты.
Upstream Kubernetes позволяет создавать службы типа LoadBalancer, но не включает реализацию балансировщика нагрузки по умолчанию, поэтому эти службы останутся
pending
, пока они не будут установлены. Многим размещенным службам требуется облачный провайдер, такой как Amazon EC2 или Microsoft Azure, чтобы предложить реализацию внешней балансировки нагрузки. Напротив, K3s ServiceLB позволяет использовать службы LoadBalancer без облачного провайдера или какой-либо дополнительной настройки.Как работает сервис LB
Контроллер ServiceLB отслеживает Kubernetes Services с полем
spec.type
, установленным наLoadBalancer
.Для каждой службы LoadBalancer создается DaemonSet в пространстве имен
kube-system
. Этот DaemonSet, в свою очередь, создает поды с префиксомsvc-
на каждом узле. Эти поды используют iptables для перенаправления трафика из NodePort пода на адрес и порт ClusterIP службы.Если модуль ServiceLB работает на узле с настроенным внешним IP-адресом, внешний IP-адрес узла заносится в список адресов
status.loadBalancer.ingress
службы. В противном случае используется внутренний IP-адрес узла.Если создается несколько служб LoadBalancer, для каждой службы создается отдельный DaemonSet.
На одном узле можно разместить несколько Сервисов, если они используют разные порты.
Если вы попытаетесь создать службу LoadBalancer, которая прослушивает порт 80, ServiceLB попытается найти свободный хост в кластере для порта 80. Если хост с этим портом недоступен, LB останется в состоянии ожидания.
В качестве возможного решения я бы рекомендовал использовать Traefik
, так как это контроллер Ingress
по умолчанию в K3S
.
Статус Pending
на вашем LoadBalancer
, скорее всего, вызван другой службой, используемой на этом порту (Traefik
).
Если вы хотите по-прежнему использовать NGINX
, на той же странице документации объясняется, как отключить Traefik
.
Я был бы осторожнее с удалением ресурсов, как это сделали вы. Следующая команда:
k delete all --all -n ingress-nginx
Не удалит все созданные ресурсы. На мой взгляд, лучшим способом было бы использовать команду, которую вы использовали для создания, и вместо:
kubectl create -f ...
Использовать:
kubectl delete -f ...
Я предполагаю, что вы не изменили свое определение Ingress
, поэтому вы получаете сообщение об ошибке, и kubectl get ingress
показывает неверные результаты.
Что вам нужно будет сделать:
spec:
ingressClassName: nginx # <-- DELETE IT OR CHANGE TO "traefik"
Либо удаление, либо изменение должны работать, так как traefik
установлено по умолчанию IngressClass
для этой настройки.
@ user842225 Я воспроизвел вашу настройку и обновил ответ. Взглянем.
Привет спасибо! Я также понял и точно так, как вы сказали.
Спасибо! Не могли бы вы проверить мой обновленный пост выше на основе вашего ответа?