Remove GKE / GCP specific docs (#3731)

This commit is contained in:
Ashleigh Brennan 2021-06-04 16:02:45 -05:00 committed by GitHub
parent 9258df348b
commit 7fcd22f69b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 0 additions and 799 deletions

View File

@ -1,99 +0,0 @@
---
title: "Assigning a static IP address for Knative on Kubernetes Engine"
linkTitle: "Assigning static IPs - GKE"
weight: 35
type: "docs"
---
# Assigning a static IP address for Knative on Kubernetes Engine
If you are running Knative on Google Kubernetes Engine and want to use a
[custom domain](./using-a-custom-domain.md) with your apps, you need to
configure a static IP address to ensure that your custom domain mapping doesn't
break.
Knative configures an Istio Gateway CRD named `knative-ingress-gateway` under
the `knative-serving` namespace to serve all incoming traffic within the Knative
service mesh. The IP address to access the gateway is the external IP address of
the "istio-ingressgateway" service under the `istio-system` namespace.
Therefore, in order to set a static IP for the gateway you must to set the
external IP address of the `istio-ingressgateway` service to a static IP.
If you have configured a
[custom ingress gateway](./setting-up-custom-ingress-gateway.md), replace
`istio-ingressgateway` with the name of your gateway service in the steps below.
## Step 1: Reserve a static IP address
You can reserve a regional static IP address using the Google Cloud SDK or the
Google Cloud Platform console.
Using the Google Cloud SDK:
1. Enter the following command, replacing IP_NAME and REGION with appropriate
values. For example, select the `us-west1` region if you deployed your
cluster to the `us-west1-c` zone:
```shell
gcloud beta compute addresses create IP_NAME --region=REGION
```
For example:
```shell
gcloud beta compute addresses create knative-ip --region=us-west1
```
1. Enter the following command to get the newly created static IP address:
```shell
gcloud beta compute addresses list
```
In the
[GCP console](https://console.cloud.google.com/networking/addresses/add?_ga=2.97521754.-475089713.1523374982):
1. Enter a name for your static address.
1. For **IP version**, choose IPv4.
1. For **Type**, choose **Regional**.
1. From the **Region** drop-down, choose the region where your Knative cluster
is running.
For example, select the `us-west1` region if you deployed your cluster to
the `us-west1-c` zone.
1. Leave the **Attached To** field set to `None` since we'll attach the IP
address through a config-map later.
1. Copy the **External Address** of the static IP you created.
## Step 2: Update the external IP of `istio-ingressgateway` service
Run following command to configure the external IP of the `istio-ingressgateway`
service to the static IP that you reserved:
```shell
INGRESSGATEWAY=istio-ingressgateway
kubectl patch svc $INGRESSGATEWAY --namespace istio-system --patch '{"spec": { "loadBalancerIP": "<your-reserved-static-ip>" }}'
```
## Step 3: Verify the static IP address of `istio-ingressgateway` service
Run the following command to ensure that the external IP of the ingressgateway
service has been updated:
```shell
kubectl get svc $INGRESSGATEWAY --namespace istio-system
```
The output should show the assigned static IP address under the EXTERNAL-IP
column:
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
xxxxxxx-ingressgateway LoadBalancer 12.34.567.890 98.765.43.210 80:32380/TCP,443:32390/TCP,32400:32400/TCP 5m
```
> Note: Updating the external IP address can take several minutes.
The [external IP address](https://console.cloud.google.com/networking/addresses/list) should have a value now in the `In use by` column and should not be `None` anymore:
![External IP address assigned](./images/gke-assigning-static-ip-address.png)

View File

@ -1,267 +0,0 @@
---
title: "Configuring HTTPS with cert-manager and Google Cloud DNS"
linkTitle: "Configuring HTTPS with Cloud DNS"
weight: 63
type: "docs"
---
# Configuring HTTPS with cert-manager and Google Cloud DNS
You can use cert-manager with Knative to automatically provision TLS
certificates from Let's Encrypt and use
[Google Cloud DNS](https://cloud.google.com/dns/) to handle HTTPS requests and
validate DNS challenges.
The following guide demonstrates how you can setup Knative to handle secure
HTTPS requests on Google Cloud Platform, specifically using cert-manager for TLS
certificates and [Google Cloud DNS](https://cloud.google.com/dns/) as the DNS
provider.
Learn more about using TLS certificates in Knative:
- [Configuring HTTPS with TLS certificates](./using-a-tls-cert.md)
- [Enabling automatic TLS certificate provisioning](./using-auto-tls.md)
## Before you begin
You must meet the following prerequisites to configure Knative with cert-manager
and Cloud DNS:
- You must have a
[GCP project ID with owner privileges](https://console.cloud.google.com/cloud-resource-manager).
- [Google Cloud DNS](https://cloud.google.com/dns/docs/how-to) must set up and
configure for your domain.
- You must have a Knative cluster with the following requirements:
- Knative Serving running.
- The Knative cluster must be running on Google Cloud Platform. For details
about installing the Serving component, see the
[Knative installation guides](../install/).
- Your Knative cluster must be configured to use a
[custom domain](./using-a-custom-domain.md).
- [cert-manager v1.0.0 or higher installed](./installing-cert-manager.md)
- Your DNS provider must be setup and configured to your domain.
## Creating a service account and using a Kubernetes secret
To allow cert-manager to access and update the DNS record, you must create a
service account in GCP, add the key in a Kubernetes secret, and then add that
secret to your Knative cluster.
Note that several example names are used in the following commands, for example
secret or file names, which can all be changed to your liking.
1. Create a service account in GCP with `dns.admin` project role by running the
following commands, where `<your-project-id>` is the ID of your GCP project:
```shell
# Set this to your GCP project ID
export PROJECT_ID=<your-project-id>
# Name of the service account you want to create.
export CLOUD_DNS_SA=cert-manager-cloud-dns-admin
gcloud --project $PROJECT_ID iam service-accounts \
create $CLOUD_DNS_SA \
--display-name "Service Account to support ACME DNS-01 challenge."
# Fully-qualified service account name also has project-id information.
export CLOUD_DNS_SA=$CLOUD_DNS_SA@$PROJECT_ID.iam.gserviceaccount.com
# Bind the role dns.admin to this service account, so it can be used to support
# the ACME DNS01 challenge.
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:$CLOUD_DNS_SA \
--role roles/dns.admin
```
1. Download the service account key by running the following commands:
```shell
# Make a temporary directory to store key
KEY_DIRECTORY=`mktemp -d`
# Download the secret key file for your service account.
gcloud iam service-accounts keys create $KEY_DIRECTORY/cloud-dns-key.json \
--iam-account=$CLOUD_DNS_SA
```
1. Create a Kubernetes secret and then add that secret to your Knative cluster
by running the following commands:
```shell
# Upload that as a secret in your Kubernetes cluster.
kubectl create secret --namespace cert-manager generic cloud-dns-key \
--from-file=key.json=$KEY_DIRECTORY/cloud-dns-key.json
# Delete the local secret
rm -rf $KEY_DIRECTORY
```
## Adding your service account to cert-manager
Create a `ClusterIssuer` configuration file to define how cert-manager obtains
TLS certificates and how the requests are validated with Cloud DNS.
1. Run the following command to create the `ClusterIssuer` configuration. The
following creates the `letsencrypt-issuer` `ClusterIssuer`, that includes
your Let's Encrypt account info, `DNS-01` challenge type, and Cloud DNS
provider info, including your `cert-manager-cloud-dns-admin` service account.
```shell
kubectl apply --filename - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-issuer
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
# This will register an issuer with LetsEncrypt. Replace
# with your admin email address.
email: myemail@gmail.com
privateKeySecretRef:
# Set privateKeySecretRef to any unused secret name.
name: letsencrypt-issuer
solvers:
- dns01:
clouddns:
# Set this to your GCP project-id
project: $PROJECT_ID
# Set this to the secret that we publish our service account key
# in the previous step.
serviceAccountSecretRef:
name: cloud-dns-key
key: key.json
EOF
```
1. Ensure that `letsencrypt-issuer` is created successfully by running the
following command:
```shell
kubectl get clusterissuer --namespace cert-manager letsencrypt-issuer --output yaml
```
Result: The `Status.Conditions` should include `Ready=True`. For example:
```yaml
status:
acme:
uri: https://acme-v02.api.letsencrypt.org/acme/acct/40759665
conditions:
- lastTransitionTime: 2018-08-23T01:44:54Z
message: The ACME account was registered with the ACME server
reason: ACMEAccountRegistered
status: "True"
type: Ready
```
## Add `letsencrypt-issuer` to your ingress secret to configure your certificate
To configure how Knative uses your TLS certificates, you create a `Certificate`
to add `letsencrypt-issuer` to the `istio-ingressgateway-certs` secret.
Note that `istio-ingressgateway-certs` will be overridden if the secret already
exists.
1. Run the following commands to create the `my-certificate` `Certificate`,
where `<your-domain.com>` is your domain:
```shell
# Change this value to the domain you want to use.
export DOMAIN=<your-domain.com>
kubectl apply --filename - <<EOF
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-certificate
namespace: istio-system
spec:
secretName: istio-ingressgateway-certs
issuerRef:
name: letsencrypt-issuer
kind: ClusterIssuer
dnsNames:
- "*.default.$DOMAIN"
- "*.other-namespace.$DOMAIN"
EOF
```
1. Ensure that `my-certificate` is created successfully by running the following
command:
```shell
kubectl get certificate --namespace istio-system my-certificate --output yaml
```
Result: The `Status.Conditions` should include `Ready=True`. For example:
```yaml
status:
acme:
order:
url: https://acme-v02.api.letsencrypt.org/acme/order/40759665/45358362
conditions:
- lastTransitionTime: 2018-08-23T02:28:44Z
message: Certificate issued successfully
reason: CertIssued
status: "True"
type: Ready
```
Note: If `Status.Conditions` is `Ready=False`, that indicates a failure to
obtain a certificate, which should be explained in the accompanying error
message.
## Configuring the Knative ingress gateway
To configure the `knative-ingress-gateway` to use the TLS certificate that you
created, append the `tls:` section to the end of your HTTPS port configuration.
Run the following commands to configure Knative to use HTTPS connections and
send a `301` redirect response for all HTTP requests:
```shell
kubectl apply --filename - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: knative-ingress-gateway
namespace: knative-serving
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
tls:
# Sends 301 redirect for all http requests.
# Omit to allow http and https.
httpsRedirect: true
- port:
number: 443
name: https
protocol: HTTPS
hosts:
- "*"
tls:
mode: SIMPLE
privateKey: /etc/istio/ingressgateway-certs/tls.key
serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
EOF
```
Congratulations, you can now access your Knative services with secure HTTPS
connections. Your Knative cluster is configured to use cert-manager to manually
obtain TLS certificates but see the following section about automating that
process.
## Configure Knative for automatic certificate provisioning
You can update your Knative configuration to automatically obtain and renew TLS
certificates before they expire. To learn more about automatic certificates, see
[Enabling automatic TLS certificate provisioning](./using-auto-tls.md).

View File

@ -1,429 +0,0 @@
---
title: "Using ExternalDNS on Google Cloud Platform to automate DNS setup"
#linkTitle: "OPTIONAL_ALTERNATE_NAV_TITLE"
weight: 70
type: "docs"
---
# Using ExternalDNS on Google Cloud Platform to automate DNS setup
[ExternalDNS](https://github.com/kubernetes-incubator/external-dns) is a tool
that synchronizes exposed Kubernetes Services and Ingresses with DNS providers.
This doc explains how to set up ExternalDNS within a Knative cluster using
[Google Cloud DNS](https://cloud.google.com/dns/) to automate the process of
publishing the Knative domain.
## Set up environtment variables
Run the following command to configure the environment variables
```shell
export PROJECT_NAME=<your-google-cloud-project-name>
export CUSTOM_DOMAIN=<your-custom-domain-used-in-knative>
export CLUSTER_NAME=<knative-cluster-name>
export CLUSTER_ZONE=<knative-cluster-zone>
```
## Set up Kubernetes Engine cluster with CloudDNS read/write permissions
There are two ways to set up a Kubernetes Engine cluster with CloudDNS
read/write permissions.
### Cluster with Cloud DNS scope
You can create a GKE cluster with Cloud DNS scope by entering the following
command:
```shell
gcloud container clusters create $CLUSTER_NAME \
--zone=$CLUSTER_ZONE \
--cluster-version=latest \
--machine-type=n1-standard-4 \
--enable-autoscaling --min-nodes=1 --max-nodes=10 \
--enable-autorepair \
--scopes=service-control,service-management,compute-rw,storage-ro,cloud-platform,logging-write,monitoring-write,pubsub,datastore,"https://www.googleapis.com/auth/ndev.clouddns.readwrite" \
--num-nodes=3
```
Note that by using this way, any pod within the cluster will have permissions to
read/write CloudDNS.
### Cluster with Cloud DNS Admin Service Account credential
1. Create a GKE cluster without Cloud DNS scope by entering the following
command:
```shell
gcloud container clusters create $CLUSTER_NAME \
--zone=$CLUSTER_ZONE \
--cluster-version=latest \
--machine-type=n1-standard-4 \
--enable-autoscaling --min-nodes=1 --max-nodes=10 \
--enable-autorepair \
--scopes=service-control,service-management,compute-rw,storage-ro,cloud-platform,logging-write,monitoring-write,pubsub,datastore \
--num-nodes=3
```
2. Create a new service account for Cloud DNS admin role.
```shell
# Name of the service account you want to create.
export CLOUD_DNS_SA=cloud-dns-admin
gcloud --project $PROJECT_NAME iam service-accounts \
create $CLOUD_DNS_SA \
--display-name "Service Account to support ACME DNS-01 challenge."
```
3. Bind the role `dns.admin` to the newly created service account.
```shell
# Fully-qualified service account name also has project-id information.
export CLOUD_DNS_SA=$CLOUD_DNS_SA@$PROJECT_NAME.iam.gserviceaccount.com
gcloud projects add-iam-policy-binding $PROJECT_NAME \
--member serviceAccount:$CLOUD_DNS_SA \
--role roles/dns.admin
```
4. Download the secret key file for your service account.
```shell
gcloud iam service-accounts keys create ~/key.json \
--iam-account=$CLOUD_DNS_SA
```
5. Upload the service account credential to your cluster. This command uses the
secret name `cloud-dns-key`, but you can choose a different name.
```shell
kubectl create secret generic cloud-dns-key \
--from-file=key.json=$HOME/key.json
```
6. Delete the local secret
```shell
rm ~/key.json
```
Now your cluster has the credential of your CloudDNS admin service account. And
it can be used to access your Cloud DNS. You can enforce the access of the
credentail secret within your cluster, so that only the pods that have the
permission to get the credential secret can access your Cloud DNS.
## Set up Knative
1. Follow the [instruction](../install/) to install Knative on your
cluster.
1. Configure Knative to use your custom domain.
```shell
kubectl edit cm config-domain --namespace knative-serving
```
This command opens your default text editor and allows you to edit the config
map.
```
apiVersion: v1
data:
example.com: ""
kind: ConfigMap
[...]
```
Edit the file to replace `example.com` with your custom domain (the value of
`$CUSTOM_DOMAIN`) and save your changes. In this example, we use domain
`external-dns-test.my-org.do` for all routes:
```
apiVersion: v1
data:
external-dns-test.my-org.do: ""
kind: ConfigMap
[...]
```
## Set up ExternalDNS
This guide uses Google Cloud Platform as an example to show how to set up
ExternalDNS. You can find detailed instructions for other cloud providers in the
[ExternalDNS documentation](https://github.com/kubernetes-incubator/external-dns#deploying-to-a-cluster).
### Create a DNS zone for managing DNS records
Skip this step if you already have a zone for managing the DNS records of your
custom domain.
A DNS zone which will contain the managed DNS records needs to be created.
Use the following command to create a DNS zone with
[Google Cloud DNS](https://cloud.google.com/dns/):
```shell
export DNS_ZONE_NAME=<dns-zone-name>
gcloud dns managed-zones create $DNS_ZONE_NAME \
--dns-name $CUSTOM_DOMAIN \
--description "Automatically managed zone by kubernetes.io/external-dns"
```
Make a note of the nameservers that were assigned to your new zone.
```shell
gcloud dns record-sets list \
--zone $DNS_ZONE_NAME \
--name $CUSTOM_DOMAIN \
--type NS
```
You should see output similar to the following assuming your custom domain is
`external-dns-test.my-org.do`:
```
NAME TYPE TTL DATA
external-dns-test.my-org.do. NS 21600 ns-cloud-e1.googledomains.com.,ns-cloud-e2.googledomains.com.,ns-cloud-e3.googledomains.com.,ns-cloud-e4.googledomains.com.
```
In this case, the DNS nameservers are `ns-cloud-{e1-e4}.googledomains.com`.
Yours could differ slightly, e.g. {a1-a4}, {b1-b4} etc.
If this zone has the parent zone, you need to add NS records of this zone into
the parent zone so that this zone can be found from the parent. Assuming the
parent zone is `my-org-do` and the parent domain is `my-org.do`, and the parent
zone is also hosted at Google Cloud DNS, you can follow these steps to add the
NS records of this zone into the parent zone:
```shell
gcloud dns record-sets transaction start --zone "my-org-do"
gcloud dns record-sets transaction add ns-cloud-e{1..4}.googledomains.com. \
--name "external-dns-test.my-org.do." --ttl 300 --type NS --zone "my-org-do"
gcloud dns record-sets transaction execute --zone "my-org-do"
```
### Deploy ExternalDNS
Firstly, choose the manifest of ExternalDNS.
Use below manifest if you set up your cluster with
[CloudDNS scope](#cluster-with-cloud-dns-scope).
```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"]
verbs: ["get", "watch", "list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
- apiGroups: ["extensions"]
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: extensions/v1beta1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: registry.opensource.zalan.do/teapot/external-dns:latest
args:
- --source=service
- --domain-filter=$CUSTOM_DOMAIN # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
- --provider=google
- --google-project=$PROJECT_NAME # Use this to specify a project different from the one external-dns is running inside
- --policy=sync # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
- --registry=txt
- --txt-owner-id=my-identifier
```
Or use below manifest if you set up your cluster with
[CloudDNS service account credential](#cluster-with-cloud-dns-admin-service-account-credential).
```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"]
verbs: ["get", "watch", "list"]
- apiGroups: [""]
resources: ["pods,secrets"]
verbs: ["get", "watch", "list"]
- apiGroups: ["extensions"]
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: extensions/v1beta1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
template:
metadata:
labels:
app: external-dns
spec:
volumes:
- name: google-cloud-key
secret:
secretName: cloud-dns-key
serviceAccountName: external-dns
containers:
- name: external-dns
image: registry.opensource.zalan.do/teapot/external-dns:latest
volumeMounts:
- name: google-cloud-key
mountPath: /var/secrets/google
env:
- name: GOOGLE_APPLICATION_CREDENTIALS
value: /var/secrets/google/key.json
args:
- --source=service
- --domain-filter=$CUSTOM_DOMAIN # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
- --provider=google
- --google-project=$PROJECT_NAME # Use this to specify a project different from the one external-dns is running inside
- --policy=sync # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
- --registry=txt
- --txt-owner-id=my-identifier
```
Then use the following command to apply the manifest you chose to install
ExternalDNS
```shell
cat <<EOF | kubectl apply --filename -
<your-chosen-manifest>
EOF
```
You should see ExternalDNS is installed by running:
```shell
kubectl get deployment external-dns
```
### Configuring Knative Gateway service
In order to publish the Knative Gateway service, the annotation
`external-dns.alpha.kubernetes.io/hostname: '*.$CUSTOM_DOMAIN` needs to be added
into Knative gateway service:
```shell
INGRESSGATEWAY=istio-ingressgateway
kubectl edit svc $INGRESSGATEWAY --namespace istio-system
```
This command opens your default text editor and allows you to add the annotation
to `istio-ingressgateway` service. After you've added your annotation, your
file may look similar to this (assuming your custom domain is
`external-dns-test.my-org.do`):
```
apiVersion: v1
kind: Service
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: '*.external-dns-test.my-org.do'
...
```
### Verify ExternalDNS works
After roughly two minutes, check that a corresponding DNS record for your
service was created.
```shell
gcloud dns record-sets list --zone $DNS_ZONE_NAME --name "*.$CUSTOM_DOMAIN."
```
You should see output similar to:
```
NAME TYPE TTL DATA
*.external-dns-test.my-org.do. A 300 35.231.248.30
*.external-dns-test.my-org.do. TXT 300 "heritage=external-dns,external-dns/owner=my-identifier,external-dns/resource=service/istio-system/istio-ingressgateway"
```
### Verify domain has been published
You can check if the domain has been published to the Internet be entering the
following command:
```shell
host test.external-dns-test.my-org.do
```
You should see the below result after the domain is published:
```
test.external-dns-test.my-org.do has address 35.231.248.30
```
> Note: The process of publishing the domain to the Internet can take several
> minutes.

View File

@ -99,10 +99,6 @@ nav:
- Feature/Extension Flags: serving/feature-flags.md - Feature/Extension Flags: serving/feature-flags.md
- Configuring the ingress gateway: serving/setting-up-custom-ingress-gateway.md - Configuring the ingress gateway: serving/setting-up-custom-ingress-gateway.md
- Setting up a custom domain: serving/using-a-custom-domain.md - Setting up a custom domain: serving/using-a-custom-domain.md
- GKE Topics:
- Assigning static IPs - GKE: serving/gke-assigning-static-ip-address.md
- Using ExternalDNS on Google Cloud Platform to automate DNS setup: serving/using-external-dns-on-gcp.md
- Configuring HTTPS with Cloud DNS: serving/using-cert-manager-on-gcp.md
- Code samples: - Code samples:
- Overview: serving/samples/README.md - Overview: serving/samples/README.md
- Routing and managing traffic: serving/samples/blue-green-deployment.md - Routing and managing traffic: serving/samples/blue-green-deployment.md