Использование Traefik и cert-manager для обслуживания защищенного сайта
Из этого туториала вы узнаете, как установить Traefik поверх нового кластера kubernetes. С помощью простого сервиса nginx будут показаны различные решения о том, как обслуживать страницу с помощью самозаверяющего сертификата, зашифрованного промежуточного и производственного сертификата. Все сертификат вещь сделана с CERT-менеджером .
Вы должны быть знакомы с основами использования kubernetes и иметь под рукой работающий кластер k8s.
Предпосылки
Все шаги могут быть выполнены как есть на машине, где
!!! Если у вас есть только один кластер узлов, позаботьтесь о том, чтобы испортить мастер-узел для приема модулей:
Вы можете определить конфигурацию traefik с помощью флагов cli или файла toml. TOML-файл легче обрабатывать для сложных настроек. Из-за простоты в этом руководстве используются флаги cli.
!!! Конфиг использует
!!! Используемая конфигурация traefik не готова к производству! Вы должны использовать базовую авторизацию http для защиты панели в сочетании с автоматическим перенаправлением https. Для производственной среды также рекомендуется настроить traefik в отдельном пространстве имен.
Приведенная выше конфигурация публикует панель мониторинга Traefik для порта
Получить
Вы также можете показать журналы для модуля traefik, используя его метку.
Вы можете проверить, указывает ли ваш домен правильный IP с помощью:
Сохраните ваш домен как переменную среды для дальнейшего использования:
Убедитесь, что модуль nginx создан и
После применения изменений, откройте
Если вы откроете журнал pods и перезагрузите домен в браузере, вы увидите запросы в журналах nginx.
Let's Encrypt это очень простая задача. Нет более сложной обработки сертификатов.
Через несколько секунд все капсулы должны быть в
!!! Команда
Вы можете проверить статус
Если вы открываете
Викимедиа )
Получить статус с
Содержание сертификатов хранится в секрете. Чтобы создать новый сертификат, мы должны удалить этот секрет. Также удалите сертификат, иначе
Запрос занимает около 30 секунд. Вы можете постоянно проверять статус с помощью команды bash
!!! Для того, чтобы заставить обновления, просто удалите секрет , содержащий сертификат:
Если вы используете свой собственный домен, процесс должен работать.
Проверь состояние
Опять же, проверьте статус запроса и проверьте журналы cert-manager через минуту, если сертификат не отображается
!!! Используемая конфигурация traefik не готова к производству! Вы должны использовать (как минимум) базовую авторизацию http для защиты панели в сочетании с автоматическим перенаправлением https.
Вы должны быть знакомы с основами использования kubernetes и иметь под рукой работающий кластер k8s.
Предпосылки
- Работающий кластер kubernetes (создайте свой собственный с этим руководством )
- Плавающий IP-адрес, указывающий на ваш кластер или общедоступный IP-адрес одного из ваших узлов (
<10.0.0.1>
в этом учебном пособии<>
они не являются частью IP-адреса) - Знакомство с Linux и работа на оболочке
kubectl
инструмент командной строки установлен- Адрес электронной почты для использования с Let's Encrypt , этот учебник использует:
mail@example.com
- Знакомство с понятиями Кубернетеса
- Действительный домен или поддомен с доступом к настройке DNS.
Все шаги могут быть выполнены как есть на машине, где
kubectl
установлен. Большинство шагов используют запись heredoc для предотвращения создания файла конфигурации. Используемые сервисы kubernetes будут использовать другой синтаксис, где это возможно. Это покажет вам разные возможности.Шаг 1 - Разверните Traefik в качестве входного контроллера
Следующая настройка основана на официальных инструкциях по настройке .Шаг 1.1 - Создайте необходимые роли RBAC
Traefik необходимо настроить некоторые роли kubernetes, прежде чем можно будет выполнить настройку службы.kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/traefik-rbac.yaml
Шаг 1.2 - Настройка Traefik
Как указано в документации, traefik может быть установлен какController
или DaemonSet
. В этом уроке мы используем DaemonSet
развертывание. Если у вас есть кластер, состоящий из нескольких узлов (мастер или рабочие), на каждом узле будет создан ровно один модуль traefik без дополнительной настройки.!!! Если у вас есть только один кластер узлов, позаботьтесь о том, чтобы испортить мастер-узел для приема модулей:
kubectl taint nodes --all node-role.kubernetes.io/master-
Вы можете определить конфигурацию traefik с помощью флагов cli или файла toml. TOML-файл легче обрабатывать для сложных настроек. Из-за простоты в этом руководстве используются флаги cli.
!!! Конфиг использует
type
LoadBalancer
вместо NodePort
. Это должно работать для установок с голым металлом, metallb
как в этом уроке . Если вы используете облачного провайдера с внешним балансировщиком нагрузки, вы можете использовать NodePort
вместо этого.!!! Используемая конфигурация traefik не готова к производству! Вы должны использовать базовую авторизацию http для защиты панели в сочетании с автоматическим перенаправлением https. Для производственной среды также рекомендуется настроить traefik в отдельном пространстве имен.
cat << EOF | kubectl apply -f -
---
apiVersion: v1
kind: ServiceAccount
metadаta:
name: traefik-ingress-controller
namespace: kube-system
---
kind: DaemonSet
apiVersion: extensions/v1beta1
metadаta:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
template:
metadаta:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
containers:
- image: traefik:v1.7
name: traefik-ingress-lb
ports:
- name: http
containerPort: 80
hostPort: 80
- name: https
containerPort: 443
hostPort: 443
- name: dashboard
containerPort: 8080
hostPort: 8080
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
args:
- --api
- --accesslog
- --logLevel=INFO
- --kubernetes
- --defaultentrypoints=http,https
- --entrypoints=Name:https Address::443 TLS
- --entrypoints=Name:http Address::80
---
kind: Service
apiVersion: v1
metadаta:
name: traefik-ingress-service
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- protocol: TCP
port: 80
name: http
- protocol: TCP
port: 443
name: https
- protocol: TCP
port: 8080
name: dashboard
type: LoadBalancer
EOF
8080
и публикует порты по умолчанию, используемые для трафика HTTP: 80
и 443
.Шаг 1.3 - Подтвердите настройку
Проверьте, все ли стручкиRunning
.kubectl -n kube-system get pod
# Output:
NAME READY STATUS RESTARTS AGE
coredns-5d4dd4b4db-frkpb 1/1 Running 0 12m
coredns-5d4dd4b4db-t8z2s 1/1 Running 0 12m
etcd-k1 1/1 Running 1 11m
kube-apiserver-k1 1/1 Running 1 6m49s
kube-controller-manager-k1 1/1 Running 1 11m
kube-flannel-ds-amd64-hbk58 1/1 Running 0 5m47s
kube-proxy-dmng9 1/1 Running 1 12m
kube-scheduler-k1 1/1 Running 1 12m
traefik-ingress-controller-z8xdn 1/1 Running 0 36s
EXTERNAL-IP
назначенный на traefik-ingress-service
.kubectl -n kube-system get service
# Output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 16m
traefik-ingress-service LoadBalancer 10.109.23.93 10.0.0.1 80:31681/TCP,443:31856/TCP,8080:32684/TCP 4m23s
- журналы для конкретного модуля
kubectl -n kube-system logs -f $(kubectl -n kube-system get pods -l k8s-app=traefik-ingress-lb -o jsonpath='{.items[0].metadata.name}')
- журналы для всех модулей, полезно, если у вас есть несколько узлов
kubectl -n kube-system logs -f -l k8s-app=traefik-ingress-lb
Шаг 1.4 - Открыть панель инструментов Traefik
СозданныйService
вами, должен был получить EXTERNAL-IP
сервер. Это должен совпадать с нашим плавающим IP-адресом или общедоступным IP-адресом сервера, в зависимости от настроек. А LoadBalancer
сервис связывается с каким - то случайным портом (ы) , как вы видите в колонке PORT(S)
. Знание порта и IP - все, что вам нужно, чтобы открыть панель инструментов ( http://<10.0.0.1>:32684
).Шаг 2 - хост простой сервис nginx
На следующем этапе мы развернем простой сервис nginx и опубликуем его в вашем домене.Шаг 2.1 - Подготовьте домен
Если у вас есть собственный домен (в этом руководстве:)<example.com>
, позаботьтесь о том, чтобы A-Record
в настройках DNS создать плавающий IP-адрес вашего кластера ( <10.0.0.1>
) или публичный IP-адрес сервера. В зависимости от TTL вашего провайдера (Время жизни в секундах), распространение DNS может занять некоторое время. Поскольку DNS вашей локальной системы не будет обновляться так часто, как настройки сервера, рекомендуется также выполнить проверку на сервере.Вы можете проверить, указывает ли ваш домен правильный IP с помощью:
host <example.com>
# Outputs:
example.com has address 10.0.0.1
DOMAIN=<example.com>
Шаг 2.2 - Развертывание службы nginx
Теперь мы будем использовать настроенныеDOMAIN
прямо внутри конфига. Как видите, сервис будет создан в отдельном пространстве имен. Это рекомендуемый способ.cat << EOF | kubectl apply -f -
---
apiVersion: v1
kind: Namespace
metadаta:
name: testing
spec:
finalizers:
- kubernetes
status:
phase: Active
---
apiVersion: apps/v1beta2
kind: Deployment
metadаta:
name: nginx
namespace: testing
labels:
app: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadаta:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadаta:
name: nginx
namespace: testing
spec:
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: extensions/v1beta1
kind: Ingress
metadаta:
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/rule-type: "PathPrefixStrip"
name: nginx
namespace: testing
spec:
rules:
- host: ${DOMAIN}
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80
EOF
Running
.kubectl -n testing get pod
NAME READY STATUS RESTARTS AGE
nginx-74f6bc9c7c-bvjh5 1/1 Running 0 9s
<example.com>
в вашем браузере. Вы должны увидеть очень простую HTML-страницу сейчас.Если вы откроете журнал pods и перезагрузите домен в браузере, вы увидите запросы в журналах nginx.
kubectl -n testing logs -f $(kubectl -n testing get pods -l app=nginx -o jsonpath='{.items[0].metadata.name}')
Let's Encrypt это очень простая задача. Нет более сложной обработки сертификатов.
Traefik может использовать Let's Encrypt самостоятельно, но это не рекомендуемый способ, и в некоторых случаях может произойти сбой. Гораздо лучшим способом (в смысле do-one-thing-and-to-it-right
) является использование cert-manager
.
Шаг 3.1 - Настройка cert-менеджера
- Официальные документы: https://cert-manager.io/docs/usage/ingress/
kubectl create namespace cert-manager
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.12.0/cert-manager.yaml
RUNNING
состоянии.!!! Команда
watch
не является специальной командой kubernetes. Это просто стандартная команда Unix, которая выполняет следующую команду каждую секунду.watch kubectl -n cert-manager get pods
#Outputs:
NAME READY STATUS RESTARTS AGE
cert-manager-66c8bc8b67-5qcb4 1/1 Running 0 24s
cert-manager-cainjector-df4dc78cd-s56zv 1/1 Running 0 24s
cert-manager-webhook-5f78ff89bc-hr9ck 1/1 Running 0 24s
cert-manager
теперь готов к использованию. На следующих этапах мы опробуем различные способы создания готовых к тестированию и производству сертификатов.Шаг 3.2 - Создание самозаверяющего сертификата
В некоторых случаях, например, для внутреннего или тестового использования, вы можете легко создать самозаверяющий сертификатcert-manager
. Чтобы настроить сертификат с cert-manager
всегда нужно Issuer
, ClusterIssuer
и Certificate
Ressource.cat << EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadаta:
name: selfsigned
namespace: testing
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadаta:
name: ${DOMAIN}-cert
namespace: testing
spec:
commonName: ${DOMAIN}
secretName: ${DOMAIN}-cert
issuerRef:
name: selfsigned
EOF
Certificate
очень легко.- короткий статус
kubectl -n testing get certificate
# Outputs: 10.0.0.1.example.com-cert True 10.0.0.1.example.com-cert 47s
- полная информация и статус
kubectl -n testing describe certificate <10.0.0.1>.example.com-cert
# Outputs: ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal GeneratedKey 94s cert-manager Generated a new private key Normal Requested 94s cert-manager Created new CertificateRequest resource "10.0.0.1.example.com-cert-2241091300" Normal Issued 94s cert-manager Certificate issued successfully
Ingress
чтобы изменить это.cat << EOF | kubectl apply -f -
---
apiVersion: extensions/v1beta1
kind: Ingress
metadаta:
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/rule-type: "PathPrefixStrip"
name: nginx
namespace: testing
spec:
rules:
- host: ${DOMAIN}
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80
tls:
- hosts:
- ${DOMAIN}
secretName: ${DOMAIN}-cert
EOF
https://<example.com>
в своем браузере, вы должны сначала принять сертификат. Это связано с тем, что ваш сертификат не подписан официальным доверенным центром сертификации (CA). После добавления исключения вы должны увидеть страницу nginx по умолчанию, но защищенную https
.Викимедиа )
Процесс создания Let`s Encrypt очень прост:
- проверьте, указывает ли запрашиваемый домен на тот же IP-адрес, с которого поступил запрос
- проверьте наличие некоторых специальных файлов на указывающем сервере
- если одно из условий не выполнено, отклонить запрос
эмитент
Чтобы получить сертификат от Let's Encrypt, вам нужно настроитьIssuer
или ClusterIssuer
. A Issuer
является действительным для текущего пространства имен, a ClusterIssuer
не зависит от пространства имен.# Please replace mail with your mail
YOUR_MAIL_ADDRESS=mail@example.com
cat << EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadаta:
name: letsencrypt-staging
spec:
acme:
# You must replace this email address with your own.
# Let's Encrypt will use this to contact you about expiring
# certificates, and issues related to your account.
email: ${YOUR_MAIL_ADDRESS}
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Secret resource used to store the account's private key.
name: staging-issuer-account-key
# Add a single challenge solver, HTTP01 using nginx
solvers:
- http01:
ingress:
class: traefik
EOF
describe
или простой статус с get
.# check status
kubectl describe clusterissuer letsencrypt-staging
# Outputs:
Status:
Acme:
Last Registered Email: mail@example.com
Uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/12082973
Conditions:
Last Transition Time: 2020-01-13T15:40:13Z
Message: The ACME account was registered with the ACME server
Reason: ACMEAccountRegistered
Status: True
Type: Ready
Events: <none>
сертификат
Позаботьтесь о правильной настройке своего домена, как описано в разделеStep 2
.Содержание сертификатов хранится в секрете. Чтобы создать новый сертификат, мы должны удалить этот секрет. Также удалите сертификат, иначе
cert-manager
вы мгновенно создадите новый. Вы должны добавить метку к своему входу nginx cert-manager.io/cluster-issuer: letsencrypt-staging
. В противном случае cert-manager
не знает, какой эмитент использовать.kubectl -n testing delete certificate "${DOMAIN}-cert"
kubectl -n testing delete secret "${DOMAIN}-cert"
cat << EOF | kubectl apply -f -
---
apiVersion: extensions/v1beta1
kind: Ingress
metadаta:
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/rule-type: "PathPrefixStrip"
cert-manager.io/cluster-issuer: letsencrypt-staging
name: nginx
namespace: testing
spec:
rules:
- host: ${DOMAIN}
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80
tls:
- hosts:
- ${DOMAIN}
secretName: ${DOMAIN}-cert
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadаta:
name: ${DOMAIN}-cert
namespace: testing
spec:
commonName: ${DOMAIN}
secretName: ${DOMAIN}-cert
issuerRef:
name: letsencrypt-staging
EOF
watch
.watch kubectl -n testing describe certificate "${DOMAIN}-cert"
# Output
Status:
Conditions:
Last Transition Time: 2020-01-13T16:06:33Z
Message: Certificate is up to date and has not expired
Reason: Ready
Status: True
Type: Ready
Not After: 2020-04-12T15:06:33Z
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal GeneratedKey 2m26s cert-manager Generated a new private key
Normal Requested 2m26s cert-manager Created new CertificateRequest resource "10.0.0.1.xip.io-cert-4183194560"
Normal Issued 2m cert-manager Certificate issued successfully
cert-manager
выводит много материала во время этой операции. Если что-то идет не так (например, нет сертификата через минуту или две), вы можете проверить журналы с помощью:- статический журнал
kubectl -n cert-manager logs $(kubectl -n cert-manager get pod -l app=cert-manager -o jsonpath='{.items[0].metadata.name}')
- живой журнал
kubectl -n cert-manager logs -f --tail 20 $(kubectl -n cert-manager get pod -l app=cert-manager -o jsonpath='{.items[0].metadata.name}')
Открыть в браузере
Если вы откроете или перезагрузитеhttps://example.com
или https://$DOMAIN
в своем браузере, сертификат не будет доверенным, сопоставимым с самозаверяющим сертификатом. Имя отличается, теперь имя эмитента Fake LE Intermediate X1
вместо cert-manager
.Шаг 3.4 - Создание производственного сертификата
Если на последних этапах все работало хорошо, вы можете продолжить получать готовый сертификат Let's Encrypt. Производственный сертификат подписан официальным центром сертификации и будет надежно использоваться всеми распространенными браузерами (например, Chrome / Chromium, Firefox, IE, Edge, Safari, Opera). Полученный сертификат действителен в течение 90 дней. cert-manager обновляет сертификаты каждые 30 дней самостоятельно, поэтому срок действия сертификата никогда не истекает.!!! Для того, чтобы заставить обновления, просто удалите секрет , содержащий сертификат:
kubectl -n testing delete secret "${DOMAIN}-cert"
.Если вы используете свой собственный домен, процесс должен работать.
эмитент
YOUR_MAIL_ADDRESS=mail@example.com
cat << EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadаta:
name: letsencrypt
spec:
acme:
# You must replace this email address with your own.
# Let's Encrypt will use this to contact you about expiring
# certificates, and issues related to your account.
email: ${YOUR_MAIL_ADDRESS}
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Secret resource used to store the account's private key.
name: letsencrypt-issuer-account-key
# Add a single challenge solver, HTTP01 using nginx
solvers:
- http01:
ingress:
class: traefik
EOF
kubectl describe clusterissuer letsencrypt
# Outputs:
Status:
Acme:
Last Registered Email: mail@example.com
Uri: https://acme-v02.api.letsencrypt.org/acme/acct/75756861
Conditions:
Last Transition Time: 2020-01-13T17:08:07Z
Message: The ACME account was registered with the ACME server
Reason: ACMEAccountRegistered
Status: True
Type: Ready
Events: <none>
сертификат
Опять сбросьтеCertificate
и соответствующий Secret
.kubectl -n testing delete certificate "${DOMAIN}-cert"
kubectl -n testing delete secret "${DOMAIN}-cert"
DOMAIN=example.com
cat << EOF | kubectl apply -f -
---
apiVersion: extensions/v1beta1
kind: Ingress
metadаta:
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/rule-type: "PathPrefixStrip"
cert-manager.io/cluster-issuer: letsencrypt
name: nginx
namespace: testing
spec:
rules:
- host: ${DOMAIN}
http:
paths:
- path: /
backend:
serviceName: nginx
servicePort: 80
tls:
- hosts:
- ${DOMAIN}
secretName: ${DOMAIN}-cert
---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadаta:
name: ${DOMAIN}-cert
namespace: testing
spec:
commonName: ${DOMAIN}
secretName: ${DOMAIN}-cert
issuerRef:
name: letsencrypt
EOF
Status: True
.watch kubectl -n testing describe certificate "${DOMAIN}-cert"
# Output
Status:
Conditions:
Last Transition Time: 2020-01-13T16:06:33Z
Message: Certificate is up to date and has not expired
Reason: Ready
Status: True
Type: Ready
Not After: 2020-04-12T15:06:33Z
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal GeneratedKey 2m26s cert-manager Generated a new private key
Normal Requested 2m26s cert-manager Created new CertificateRequest resource "example.com-cert-4183194560"
Normal Issued 2m cert-manager Certificate issued successfully
kubectl -n cert-manager logs -f --tail 10 $(kubectl -n cert-manager get pod -l app=cert-manager -o jsonpath='{.items[0].metadata.name}')
Вывод
Из этого туториала вы узнаете, как настроить traefik в качестве входного контроллера в простом кластере kubernetes. Кроме того, вы должны иметь возможность защитить развернутый веб-сервис с помощью самозаверяющего сертификата TLS или сертификата Let's Encrypt.!!! Используемая конфигурация traefik не готова к производству! Вы должны использовать (как минимум) базовую авторизацию http для защиты панели в сочетании с автоматическим перенаправлением https.
Комментариев 0