diff --git a/.github/workflows/json-yaml-validate.yml b/.github/workflows/json-yaml-validate.yml index 7cf8d2503..aa861c422 100644 --- a/.github/workflows/json-yaml-validate.yml +++ b/.github/workflows/json-yaml-validate.yml @@ -17,7 +17,9 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: json-yaml-validate - uses: GrantBirki/json-yaml-validate@v3.3.0 + uses: GrantBirki/json-yaml-validate@v3.2.1 # pin @v3.2.1 bug in 3.3.0: https://github.com/GrantBirki/json-yaml-validate/issues/86 with: + # ref: https://github.com/GrantBirki/json-yaml-validate?tab=readme-ov-file#inputs- comment: "true" # enable comment mode yaml_exclude_regex: "(charts/external-dns/templates.*|mkdocs.yml)" + allow_multiple_documents: "true" diff --git a/Makefile b/Makefile index d8b7a74e5..c0c15cd2f 100644 --- a/Makefile +++ b/Makefile @@ -200,5 +200,12 @@ helm-lint: scripts/helm-tools.sh --docs .PHONY: go-dependency -go-dependency: ## Dependency maintanance +#? go-dependency: Dependency maintanance +go-dependency: go mod tidy + +.PHONY: mkdocs-serve +#? mkdocs-serve: Run the builtin development server for mkdocs +mkdocs-serve: + @$(info "contribute to documentation docs/contributing/dev-guide.md") + @mkdocs serve diff --git a/docs/contributing/dev-guide.md b/docs/contributing/dev-guide.md index 2747c7c7f..a88632256 100644 --- a/docs/contributing/dev-guide.md +++ b/docs/contributing/dev-guide.md @@ -304,3 +304,20 @@ Install required dependencies. In order to not to break system packages, we are $$ ... $$ Serving on http://127.0.0.1:8000/ ``` + +### How to add an example snippet + +Let's say we are improving tutorial location in `docs/tutorials/aws.md`. + +1. Add a snippet to `docs/snippets/aws/.` +2. Add snippet to a markdown file `docs/tutorials/aws.md` + +[[% raw %]] + +````md + ```extension + [[% include 'snippets/aws/.' %]] + ``` +```` + +[[% endraw %]] diff --git a/docs/scripts/requirements.txt b/docs/scripts/requirements.txt index 5564c82cd..27086cd3f 100644 --- a/docs/scripts/requirements.txt +++ b/docs/scripts/requirements.txt @@ -1,5 +1,6 @@ mkdocs-git-revision-date-localized-plugin == 1.2.4 mkdocs == 1.5.3 +mkdocs-macros-plugin==1.3.7 mkdocs-material == 9.5.17 mkdocs-literate-nav == 0.6.1 mkdocs-same-dir == 0.1.3 diff --git a/docs/snippets/digitalocean/deploy-nginx.yaml b/docs/snippets/digitalocean/deploy-nginx.yaml new file mode 100644 index 000000000..6c0dc1a2f --- /dev/null +++ b/docs/snippets/digitalocean/deploy-nginx.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - image: nginx + name: nginx + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx + annotations: + external-dns.alpha.kubernetes.io/hostname: my-app.example.com +spec: + selector: + app: nginx + type: LoadBalancer + ports: + - protocol: TCP + port: 80 + targetPort: 80 diff --git a/docs/snippets/digitalocean/extdns-with-rbac.yaml b/docs/snippets/digitalocean/extdns-with-rbac.yaml new file mode 100644 index 000000000..ccb603831 --- /dev/null +++ b/docs/snippets/digitalocean/extdns-with-rbac.yaml @@ -0,0 +1,64 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: external-dns +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: external-dns +rules: +- apiGroups: [""] + resources: ["services","endpoints","pods"] + verbs: ["get","watch","list"] +- apiGroups: ["extensions","networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get","watch","list"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: external-dns-viewer +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: external-dns +subjects: +- kind: ServiceAccount + name: external-dns + namespace: default +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: external-dns +spec: + replicas: 1 + selector: + matchLabels: + app: external-dns + strategy: + type: Recreate + template: + metadata: + labels: + app: external-dns + spec: + serviceAccountName: external-dns + containers: + - name: external-dns + image: registry.k8s.io/external-dns/external-dns:v0.17.0 + args: + - --source=service # ingress is also possible + - --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above. + - --provider=digitalocean + env: + - name: DO_TOKEN + valueFrom: + secretKeyRef: + name: DO_TOKEN + key: DO_TOKEN diff --git a/docs/snippets/digitalocean/extdns-without-rbac.yaml b/docs/snippets/digitalocean/extdns-without-rbac.yaml new file mode 100644 index 000000000..696e1b08e --- /dev/null +++ b/docs/snippets/digitalocean/extdns-without-rbac.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: external-dns +spec: + replicas: 1 + selector: + matchLabels: + app: external-dns + strategy: + type: Recreate + template: + metadata: + labels: + app: external-dns + spec: + containers: + - name: external-dns + image: registry.k8s.io/external-dns/external-dns:v0.17.0 + args: + - --source=service # ingress is also possible + - --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above. + - --provider=digitalocean + env: + - name: DO_TOKEN + valueFrom: + secretKeyRef: + name: DO_TOKEN + key: DO_TOKEN diff --git a/docs/snippets/exoscale/extdns.yaml b/docs/snippets/exoscale/extdns.yaml new file mode 100644 index 000000000..48ae63fa9 --- /dev/null +++ b/docs/snippets/exoscale/extdns.yaml @@ -0,0 +1,30 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: external-dns +spec: + strategy: + type: Recreate + selector: + matchLabels: + app: external-dns + template: + metadata: + labels: + app: external-dns + spec: + # Only use if you're also using RBAC + # serviceAccountName: external-dns + containers: + - name: external-dns + image: registry.k8s.io/external-dns/external-dns:v0.17.0 + args: + - --source=ingress # or service or both + - --provider=exoscale + - --domain-filter={{ my-domain }} + - --policy=sync # if you want DNS entries to get deleted as well + - --txt-owner-id={{ owner-id-for-this-external-dns }} + - --exoscale-apikey={{ api-key}} + - --exoscale-apisecret={{ api-secret }} + # - --exoscale-apizone={{ api-zone }} + # - --exoscale-apienv={{ api-env }} diff --git a/docs/snippets/exoscale/how-to-test.yaml b/docs/snippets/exoscale/how-to-test.yaml new file mode 100644 index 000000000..e302c63d3 --- /dev/null +++ b/docs/snippets/exoscale/how-to-test.yaml @@ -0,0 +1,50 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: nginx + annotations: + external-dns.alpha.kubernetes.io/target: {{ Elastic-IP-address }} +spec: + ingressClassName: nginx + rules: + - host: via-ingress.example.com + http: + paths: + - backend: + service: + name: "nginx" + port: + number: 80 + path: / + pathType: Prefix +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx +spec: + ports: + - port: 80 + targetPort: 80 + selector: + app: nginx +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx +spec: + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - image: nginx + name: nginx + ports: + - containerPort: 80 diff --git a/docs/snippets/exoscale/rbac.yaml b/docs/snippets/exoscale/rbac.yaml new file mode 100644 index 000000000..574b33564 --- /dev/null +++ b/docs/snippets/exoscale/rbac.yaml @@ -0,0 +1,34 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: external-dns + namespace: default +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: external-dns +rules: +- apiGroups: [""] + resources: ["services","endpoints","pods"] + verbs: ["get","watch","list"] +- apiGroups: ["extensions","networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get","watch","list"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: external-dns-viewer +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: external-dns +subjects: +- kind: ServiceAccount + name: external-dns + namespace: default diff --git a/docs/snippets/security-context/extdns-limited-privilege.yaml b/docs/snippets/security-context/extdns-limited-privilege.yaml new file mode 100644 index 000000000..6256c86e7 --- /dev/null +++ b/docs/snippets/security-context/extdns-limited-privilege.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: external-dns +spec: + strategy: + type: Recreate + selector: + matchLabels: + app: external-dns + template: + metadata: + labels: + app: external-dns + spec: + containers: + - name: external-dns + image: registry.k8s.io/external-dns/external-dns:v0.17.0 + args: + - ... # your arguments here + securityContext: + runAsNonRoot: true + runAsUser: 65534 + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"] diff --git a/docs/tutorials/digitalocean.md b/docs/tutorials/digitalocean.md index 07866a035..3ffbd17e2 100644 --- a/docs/tutorials/digitalocean.md +++ b/docs/tutorials/digitalocean.md @@ -52,103 +52,13 @@ env: ### Manifest (for clusters without RBAC enabled) ```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: external-dns -spec: - replicas: 1 - selector: - matchLabels: - app: external-dns - strategy: - type: Recreate - template: - metadata: - labels: - app: external-dns - spec: - containers: - - name: external-dns - image: registry.k8s.io/external-dns/external-dns:v0.17.0 - args: - - --source=service # ingress is also possible - - --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above. - - --provider=digitalocean - env: - - name: DO_TOKEN - valueFrom: - secretKeyRef: - name: DO_TOKEN - key: DO_TOKEN +[[% include 'digitalocean/extdns-without-rbac.yaml' %]] ``` ### Manifest (for clusters with RBAC enabled) ```yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-dns ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: external-dns -rules: -- apiGroups: [""] - resources: ["services","endpoints","pods"] - verbs: ["get","watch","list"] -- apiGroups: ["extensions","networking.k8s.io"] - resources: ["ingresses"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["nodes"] - verbs: ["list"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: external-dns-viewer -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: external-dns -subjects: -- kind: ServiceAccount - name: external-dns - namespace: default ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: external-dns -spec: - replicas: 1 - selector: - matchLabels: - app: external-dns - strategy: - type: Recreate - template: - metadata: - labels: - app: external-dns - spec: - serviceAccountName: external-dns - containers: - - name: external-dns - image: registry.k8s.io/external-dns/external-dns:v0.17.0 - args: - - --source=service # ingress is also possible - - --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above. - - --provider=digitalocean - env: - - name: DO_TOKEN - valueFrom: - secretKeyRef: - name: DO_TOKEN - key: DO_TOKEN +[[% include 'digitalocean/extdns-with-rbac.yaml' %]] ``` ## Deploying an Nginx Service @@ -156,40 +66,7 @@ spec: Create a service file called 'nginx.yaml' with the following contents: ```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: nginx -spec: - replicas: 1 - selector: - matchLabels: - app: nginx - template: - metadata: - labels: - app: nginx - spec: - containers: - - image: nginx - name: nginx - ports: - - containerPort: 80 ---- -apiVersion: v1 -kind: Service -metadata: - name: nginx - annotations: - external-dns.alpha.kubernetes.io/hostname: my-app.example.com -spec: - selector: - app: nginx - type: LoadBalancer - ports: - - protocol: TCP - port: 80 - targetPort: 80 +[[% include 'digitalocean/deploy-nginx.yaml' %]] ``` Note the annotation on the service; use the same hostname as the DigitalOcean DNS zone created above. diff --git a/docs/tutorials/exoscale.md b/docs/tutorials/exoscale.md index 4b2eeb6c4..ea80414ab 100644 --- a/docs/tutorials/exoscale.md +++ b/docs/tutorials/exoscale.md @@ -21,36 +21,7 @@ Deploying external DNS for Exoscale is actually nearly identical to deploying it for other providers. This is what a sample `deployment.yaml` looks like: ```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: external-dns -spec: - strategy: - type: Recreate - selector: - matchLabels: - app: external-dns - template: - metadata: - labels: - app: external-dns - spec: - # Only use if you're also using RBAC - # serviceAccountName: external-dns - containers: - - name: external-dns - image: registry.k8s.io/external-dns/external-dns:v0.17.0 - args: - - --source=ingress # or service or both - - --provider=exoscale - - --domain-filter={{ my-domain }} - - --policy=sync # if you want DNS entries to get deleted as well - - --txt-owner-id={{ owner-id-for-this-external-dns }} - - --exoscale-apikey={{ api-key}} - - --exoscale-apisecret={{ api-secret }} - # - --exoscale-apizone={{ api-zone }} - # - --exoscale-apienv={{ api-env }} +[[% include 'exoscale/extdns.yaml' %]] ``` Optional arguments `--exoscale-apizone` and `--exoscale-apienv` define [Exoscale API Zone](https://community.exoscale.com/documentation/platform/exoscale-datacenter-zones/) @@ -61,43 +32,7 @@ Optional arguments `--exoscale-apizone` and `--exoscale-apienv` define [Exoscale If your cluster is RBAC enabled, you also need to setup the following, before you can run external-dns: ```yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: external-dns - namespace: default - ---- - -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: external-dns -rules: -- apiGroups: [""] - resources: ["services","endpoints","pods"] - verbs: ["get","watch","list"] -- apiGroups: ["extensions","networking.k8s.io"] - resources: ["ingresses"] - verbs: ["get","watch","list"] -- apiGroups: [""] - resources: ["nodes"] - verbs: ["list"] - ---- - -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: external-dns-viewer -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: external-dns -subjects: -- kind: ServiceAccount - name: external-dns - namespace: default +[[% include 'exoscale/rbac.yaml' %]] ``` ## Testing and Verification @@ -107,59 +42,7 @@ subjects: Spin up a simple nginx HTTP server with the following spec (`kubectl apply -f`): ```yaml -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: nginx - annotations: - external-dns.alpha.kubernetes.io/target: {{ Elastic-IP-address }} -spec: - ingressClassName: nginx - rules: - - host: via-ingress.example.com - http: - paths: - - backend: - service: - name: "nginx" - port: - number: 80 - path: / - pathType: Prefix - ---- - -apiVersion: v1 -kind: Service -metadata: - name: nginx -spec: - ports: - - port: 80 - targetPort: 80 - selector: - app: nginx - ---- - -apiVersion: apps/v1 -kind: Deployment -metadata: - name: nginx -spec: - selector: - matchLabels: - app: nginx - template: - metadata: - labels: - app: nginx - spec: - containers: - - image: nginx - name: nginx - ports: - - containerPort: 80 +[[% include 'exoscale/how-to-test.yaml' %]] ``` **Important!**: Don't run dig, nslookup or similar immediately (until you've diff --git a/docs/tutorials/security-context.md b/docs/tutorials/security-context.md index 0baff812b..8c25a435d 100644 --- a/docs/tutorials/security-context.md +++ b/docs/tutorials/security-context.md @@ -3,30 +3,5 @@ You can run ExternalDNS with reduced privileges since `v0.5.6` using the following `SecurityContext`. ```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: external-dns -spec: - strategy: - type: Recreate - selector: - matchLabels: - app: external-dns - template: - metadata: - labels: - app: external-dns - spec: - containers: - - name: external-dns - image: registry.k8s.io/external-dns/external-dns:v0.17.0 - args: - - ... # your arguments here - securityContext: - runAsNonRoot: true - runAsUser: 65534 - readOnlyRootFilesystem: true - capabilities: - drop: ["ALL"] +[[% include 'security-context/limited-privilege.yaml' %]] ``` diff --git a/mkdocs.yml b/mkdocs.yml index 486202a9b..4bc0c1732 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -105,3 +105,14 @@ plugins: - git-revision-date-localized: type: date fallback_to_build_date: true + # https://mkdocs-macros-plugin.readthedocs.io/en/latest/ + - macros: + include_dir: docs/snippets + # required, as default jinja markers are {{ and }} + # ref: https://mkdocs-macros-plugin.readthedocs.io/en/latest/rendering/#solution-5-altering-the-syntax-of-jinja2-for-mkdocs-macros + j2_block_start_string: '[[%' + j2_block_end_string: '%]]' + j2_variable_start_string: '[[' + j2_variable_end_string: ']]' + j2_comment_start_string: '[#' + j2_comment_end_string: '#]'