<commit_before># Deploying Ambassador to Kubernetes

In this tutorial, we'll walk through the process of deploying Ambassador in Kubernetes for ingress routing. Ambassador provides all the functionality of a traditional ingress controller (i.e., path-based routing) while exposing many additional capabilities such as [authentication](/user-guide/auth-tutorial), URL rewriting, CORS, rate limiting, and automatic metrics collection (the [mappings reference](/reference/mappings) contains a full list of supported options). For more background on Kubernetes ingress, [read this blog post](https://blog.getambassador.io/kubernetes-ingress-nodeport-load-balancers-and-ingress-controllers-6e29f1c44f2d).

Ambassador is designed to allow service authors to control how their service is published to the Internet. We accomplish this by permitting a wide range of annotations on the *service*, which Ambassador reads to configure its Envoy Proxy. Below, we'll use service annotations to configure Ambassador to map `/httpbin/` to `httpbin.org`.

## 1. Deploying Ambassador

Note: If you're using Google Kubernetes Engine with RBAC, you'll need to grant permissions to the account that will be setting up Ambassador. To do this, get your official GKE username, and then grant `cluster-admin` Role privileges to that username:

```
$ kubectl create clusterrolebinding my-cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud info --format="value(config.account)")
```

To deploy Ambassador in your default namespace, run this command if you're running in a cluster with RBAC enabled:

```shell
kubectl apply -f https://getambassador.io/yaml/ambassador/ambassador-rbac.yaml
```

Without RBAC, you can use:

```shell
kubectl apply -f https://getambassador.io/yaml/ambassador/ambassador-no-rbac.yaml
```

For production configurations, we recommend you download these YAML files as your starting point, and customize them accordingly (e.g., your namespace).

When Ambassador starts, it will notice the `getambassador.io/config` annotation on its own service, and use the `Mapping` contained in it to configure itself. (There's no restriction on what kinds of Ambassador configuration can go into the annotation, but it's important to note that Ambassador only looks at annotations on Kubernetes `service`s.)

To confirm Ambassador is running confirm that the ambassador-admin service is configured and the endpoints point to the ambassador pods:

```shell
kubectl get svc
$ kubectl get svc
NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
ambassador-admin     NodePort       10.98.211.138    <none>        8877:30319/TCP   13h
$ kubectl get endpoints
NAME                 ENDPOINTS                                         AGE
ambassador-admin     172.17.0.4:8877,172.17.0.5:8877,172.17.0.6:8877   13h
$ kubectl get pod -o wide
NAME                            READY     STATUS    RESTARTS   AGE       IP            NODE
ambassador-64cdb74db5-gzflc     1/1       Running   0          13h       172.17.0.4    minikube
ambassador-64cdb74db5-j8xqh     1/1       Running   0          13h       172.17.0.6    minikube
ambassador-64cdb74db5-ptn8f     1/1       Running   0          13h       172.17.0.5    minikube
```

Next open the Ambassador diagnostic overview webpage.  You can find the IP Address by using one of the following commands:

```bash
# AWS (for Ambassador using HTTP)
AMBASSADORURL=http://$(kubectl get service ambassador-admin --output jsonpath='{.status.loadBalancer.ingress[0].hostname}')

# GKE (for Ambassador using HTTP)
AMBASSADORURL=http://$(kubectl get service ambassador-admin --output jsonpath='{.status.loadBalancer.ingress[0].ip}')

# Minikube (for Ambassador using HTTP)
AMBASSADORURL=$(minikube service --url ambassador-admin)
```

## 2. Defining the Ambassador Service

Ambassador is deployed as a Kubernetes service. Create the following YAML and put it in a file called `ambassador-service.yaml`.

```yaml
---
apiVersion: v1
kind: Service
metadata:
  labels:
    service: ambassador
  name: ambassador
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  httpbin_mapping
      prefix: /httpbin/
      service: httpbin.org:80
      host_rewrite: httpbin.org
spec:
  type: LoadBalancer
  ports:
  - name: ambassador
    port: 80
    targetPort: 80
  selector:
    service: ambassador
```

Then, apply it to the Kubernetes with `kubectl`:

```shell
kubectl apply -f ambassador-service.yaml
```

The YAML above does several things:

* It creates a Kubernetes service for Ambassador, of type `LoadBalancer`. Note that if you're not deploying in an environment where `LoadBalancer` is a supported type, you'll need to change this to a different type of service, e.g., `NodePort`.
* It creates a test route that will route traffic from `/httpbin/` to the public `httpbin.org` service. In Ambassador, Kubernetes annotations (as shown above) are used for configuration. More commonly, you'll want to configure routes as part of your service deployment process, as shown in [this more advanced example](https://www.datawire.io/faster/canary-workflow/).

Also, note that we are using the `host_rewrite` attribute for the `httpbin_mapping` -- this forces the HTTP `Host` header, and is often a good idea when mapping to external services. Ambassador supports [many different configuration options](/reference/configuration).

## 3. Testing the Mapping

To test things out, we'll need the external IP for Ambassador (it might take some time for this to be available):

```shell
kubectl get svc -o wide ambassador
```

Eventually, this should give you something like:

```
NAME         CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
ambassador   10.11.12.13     192.168.127.12     80:31656/TCP   1m
```

You should now be able to use `curl` to `httpbin` (don't forget the trailing `/`):

```shell
$ curl 192.168.127.12/httpbin/
```

## 4. Adding a Service

You can add a service just by deploying it with an appropriate annotation. For example, we can deploy the QoTM service locally in this cluster and automatically map it through Ambassador by creating `qotm.yaml` with the following:

```yaml
---
apiVersion: v1
kind: Service
metadata:
  name: qotm
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  qotm_mapping
      prefix: /qotm/
      service: qotm
spec:
  type: ClusterIP
  selector:
    app: qotm
  ports:
  - port: 80
    name: http-qotm
    targetPort: http-api
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: qotm
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: qotm
    spec:
      containers:
      - name: qotm
        image: datawire/qotm:1.1
        ports:
        - name: http-api
          containerPort: 5000
        resources:
          limits:
            cpu: "0.1"
            memory: 100Mi
```

and then applying it with

```
kubectl apply -f qotm.yaml
```

A few seconds after the QoTM service is running, Ambassador should be configured for it. Try it with

```shell
$ curl 192.168.127.12/qotm/
```

## 5. The Diagnostics Service in Kubernetes

Note that we did not expose the diagnostics port for Ambassador, since we don't want to expose it on the Internet. To view it, we'll need to get the name of one of the ambassador pods:

```
$ kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
ambassador-3655608000-43x86   1/1       Running   0          2m
ambassador-3655608000-w63zf   1/1       Running   0          2m
```

Forwarding local port 8877 to one of the pods:

```
kubectl port-forward ambassador-3655608000-43x86 8877
```

will then let us view the diagnostics at http://localhost:8877/ambassador/v0/diag/.

## 6. Next

We've just done a quick tour of some of the core features of Ambassador: diagnostics, routing, configuration, and authentication.

- Join us on [Gitter](https://gitter.im/datawire/ambassador);
- Learn how to [add authentication](auth-tutorial.md) to existing services; or
- Learn how to [add rate limiting](rate-limiting-tutorial.md) to existing services; or<commit_msg>Update instructions to install services.<commit_after># Deploying Ambassador to Kubernetes

In this tutorial, we'll walk through the process of deploying Ambassador in Kubernetes for ingress routing. Ambassador provides all the functionality of a traditional ingress controller (i.e., path-based routing) while exposing many additional capabilities such as [authentication](/user-guide/auth-tutorial), URL rewriting, CORS, rate limiting, and automatic metrics collection (the [mappings reference](/reference/mappings) contains a full list of supported options). For more background on Kubernetes ingress, [read this blog post](https://blog.getambassador.io/kubernetes-ingress-nodeport-load-balancers-and-ingress-controllers-6e29f1c44f2d).

Ambassador is designed to allow service authors to control how their service is published to the Internet. We accomplish this by permitting a wide range of annotations on the *service*, which Ambassador reads to configure its Envoy Proxy. Below, we'll use service annotations to configure Ambassador to map `/httpbin/` to `httpbin.org`.

## 1. Deploying Ambassador

Note: If you're using Google Kubernetes Engine with RBAC, you'll need to grant permissions to the account that will be setting up Ambassador. To do this, get your official GKE username, and then grant `cluster-admin` Role privileges to that username:

```
$ kubectl create clusterrolebinding my-cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud info --format="value(config.account)")
```

To deploy Ambassador in your default namespace, run this command if you're running in a cluster with RBAC enabled:

```shell
kubectl apply -f https://getambassador.io/yaml/ambassador/ambassador-rbac.yaml
```

Without RBAC, you can use:

```shell
kubectl apply -f https://getambassador.io/yaml/ambassador/ambassador-no-rbac.yaml
```

For production configurations, we recommend you download these YAML files as your starting point, and customize them accordingly (e.g., your namespace).

When Ambassador starts, it will notice the `getambassador.io/config` annotation on its own service, and use the `Mapping` contained in it to configure itself. (There's no restriction on what kinds of Ambassador configuration can go into the annotation, but it's important to note that Ambassador only looks at annotations on Kubernetes `service`s.)

To confirm Ambassador is running confirm that the ambassador-admin service is configured and the endpoints point to the ambassador pods:

```shell
kubectl get svc
$ kubectl get svc
NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
ambassador-admin     NodePort       10.98.211.138    <none>        8877:30319/TCP   13h
$ kubectl get endpoints
NAME                 ENDPOINTS                                         AGE
ambassador-admin     172.17.0.4:8877,172.17.0.5:8877,172.17.0.6:8877   13h
$ kubectl get pod -o wide
NAME                            READY     STATUS    RESTARTS   AGE       IP            NODE
ambassador-64cdb74db5-gzflc     1/1       Running   0          13h       172.17.0.4    minikube
ambassador-64cdb74db5-j8xqh     1/1       Running   0          13h       172.17.0.6    minikube
ambassador-64cdb74db5-ptn8f     1/1       Running   0          13h       172.17.0.5    minikube
```

Next open the Ambassador diagnostic overview webpage, you can find the IP Address by using one of the following commands:

```bash
# AWS (for Ambassador using HTTP)
AMBASSADORURL=http://$(kubectl get service ambassador-admin --output jsonpath='{.status.loadBalancer.ingress[0].hostname}'):8877

# GKE (for Ambassador using HTTP)
AMBASSADORURL=http://$(kubectl get service ambassador-admin --output jsonpath='{.status.loadBalancer.ingress[0].ip}'):8877

# Minikube (for Ambassador using HTTP)
AMBASSADORURL=$(minikube service --url ambassador-admin)
```

will then let us view the diagnostics at http://$AMBASSADORURL/ambassador/v0/diag/.  If your not using minikube you will need to setup a port forward 


## 2. Defining the Ambassador Service

Ambassador is deployed as a Kubernetes service.  Create the following YAML and put it in a file called `ambassador-service.yaml`.

```yaml
---
apiVersion: v1
kind: Service
metadata:
  name: ambassador
spec:
  type: LoadBalancer
  ports:
   - port: 80
  selector:
    service: ambassador
```

It is critical that the selector label 'service: ambassador' is also a label set on the ambassador pods.  If the label is not set on the Ambassador pods routing will not work.  To confirm:

```bash
$ kubectl get pods --show-labels
NAME                          READY     STATUS    RESTARTS   AGE       LABELS
ambassador-64cdb74db5-gzflc   1/1       Running   0          14h       service=ambassador
ambassador-64cdb74db5-j8xqh   1/1       Running   0          14h       service=ambassador
ambassador-64cdb74db5-ptn8f   1/1       Running   0          14h       service=ambassador
```

Then, apply it to the Kubernetes with `kubectl`:

```shell
$ kubectl apply -f ambassador-service.yaml
```

The YAML above creates a Kubernetes service for Ambassador, of type `LoadBalancer`. All http traffic will be evaulated against the routing rules you setup.  Where the URL matches a rule it will be directed to the correct service.

Note that if you're not deploying in an environment where `LoadBalancer` is a supported type, you'll need to change this to a different type of service, e.g., `NodePort`.

## 3. Lets create our first routing service!

Create the following YAML and put it in a file called `httpbin.yaml`.

```yaml
---
apiVersion: v1
kind: Service
metadata:
  labels:
    service: apigateway
  name: httpbin
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  httpbin_mapping
      prefix: /httpbin/
      service: httpbin.org:80
      host_rewrite: httpbin.org
spec:
  ports:
  - name: httpbin
    port: 80
```

Then, apply it to the Kubernetes with `kubectl`:

```shell
$ kubectl apply -f httpbin.yaml
```

The YAML file creates a route that will route traffic from `/httpbin/` to the public `httpbin.org` service. In Ambassador, Kubernetes annotations (as shown above) are used for configuration. More commonly, you'll want to configure routes as part of your service deployment process, as shown in [this more advanced example](https://www.datawire.io/faster/canary-workflow/).

Also, note that we are using the `host_rewrite` attribute for the `httpbin_mapping` -- this forces the HTTP `Host` header, and is often a good idea when mapping to external services. Ambassador supports [many different configuration options](/reference/configuration).

If you haven't already open the Ambassador Diagnostic webpage. You should now see a route rule for the httpbin service.

## 4. Testing the Mapping

To test things out, we'll need the external IP for Ambassador (it might take some time for this to be available):

```shell
kubectl get svc -o wide ambassador
```

Eventually, this should give you something like:

```
NAME         CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
ambassador   10.11.12.13     3192.168.127.12     80:31656/TCP   1m
```
You should now be able to use `curl` to `httpbin` (don't forget the trailing `/`):

```shell
$ curl 3192.168.127.12/httpbin/
```

or on minikube 

```shell
$ minikube service list
|-------------|----------------------|-----------------------------|
|  NAMESPACE  |         NAME         |             URL             |
|-------------|----------------------|-----------------------------|
| default     | ambassador-admin     | http://192.168.99.107:30319 |
| default     | ambassador           | http://192.168.99.107:31893 |
|-------------|----------------------|-----------------------------|
$ curl http://192.168.99.107:31893/httpbin/
```

## 5. Adding a Service

You can add a service just by deploying it with an appropriate annotation. For example, we can deploy the QoTM service locally in this cluster and automatically map it through Ambassador by creating `qotm.yaml` with the following:

```yaml
---
apiVersion: v1
kind: Service
metadata:
  name: qotm
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name:  qotm_mapping
      prefix: /qotm/
      service: qotm
spec:
  selector:
    app: qotm
  ports:
  - port: 80
    name: http-qotm
    targetPort: http-api
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: qotm
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: qotm
    spec:
      containers:
      - name: qotm
        image: datawire/qotm:1.1
        ports:
        - name: http-api
          containerPort: 5000
        resources:
          limits:
            cpu: "0.1"
            memory: 100Mi
```

and then applying it with

```
kubectl apply -f qotm.yaml
```

A few seconds after the QoTM service is running, Ambassador should be configured for it. Try it with

```shell
$ curl 35.36.37.38/qotm/
```

or

```shell
$ curl http://192.168.99.107:31893/qotm/
```

## 6. The Diagnostics Service in Kubernetes

Note that we did not expose the diagnostics port for Ambassador, since we don't want to expose it on the Internet. To view it, we'll need to get the name of one of the ambassador pods:

```
$ kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
ambassador-3655608000-43x86   1/1       Running   0          2m
ambassador-3655608000-w63zf   1/1       Running   0          2m
```

Forwarding local port 8877 to one of the pods:

```
kubectl port-forward ambassador-3655608000-43x86 8877
```

will then let us view the diagnostics at http://localhost:8877/ambassador/v0/diag/.

## 6. Next

We've just done a quick tour of some of the core features of Ambassador: diagnostics, routing, configuration, and authentication.

- Join us on [Gitter](https://gitter.im/datawire/ambassador);
- Learn how to [add authentication](auth-tutorial.md) to existing services; or
- Learn how to [add rate limiting](rate-limiting-tutorial.md) to existing services; or
{'fraction_non_alphanumeric': 0.09207370257304841, 'fraction_numerical': 0.03412559965111208, 'mean_word_length': 3.008083897749618, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 10, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 26, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1337559', 'n_tokens_mistral': 5850, 'n_tokens_neox': 5182, 'n_words': 2083}