github.com/fafucoder/cilium@v1.6.11/Documentation/gettingstarted/istio.rst (about)

     1  .. only:: not (epub or latex or html)
     2  
     3      WARNING: You are looking at unreleased Cilium documentation.
     4      Please use the official rendered version released here:
     5      http://docs.cilium.io
     6  
     7  ***************************
     8  Getting Started Using Istio
     9  ***************************
    10  
    11  This document serves as an introduction to using Cilium to enforce
    12  security policies in Kubernetes micro-services managed with Istio.  It
    13  is a detailed walk-through of getting a single-node Cilium + Istio
    14  environment running on your machine.
    15  
    16  .. include:: gsg_requirements.rst
    17  
    18  .. note::
    19  
    20     If running on minikube, you may need to up the memory and CPUs
    21     available to the minikube VM from the defaults and/or the
    22     instructions provided here for the other GSGs. 5 GB and 4 CPUs
    23     should be enough for this GSG (``--memory=5120 --cpus=4``).
    24  
    25  Step 2: Install cilium-istioctl
    26  ===============================
    27  
    28  .. note::
    29  
    30     Make sure that Cilium is running in your cluster before proceeding.
    31  
    32  Download the `cilium enhanced istioctl version 1.5.7 <https://github.com/cilium/istio/releases/tag/1.5.7>`_:
    33  
    34  .. tabs::
    35    .. group-tab:: Linux
    36  
    37      .. parsed-literal::
    38  
    39       curl -L https://github.com/cilium/istio/releases/download/1.5.7/cilium-istioctl-1.5.7-linux.tar.gz | tar xz
    40  
    41    .. group-tab:: OSX
    42  
    43      .. parsed-literal::
    44  
    45       curl -L https://github.com/cilium/istio/releases/download/1.5.7/cilium-istioctl-1.5.7-osx.tar.gz | tar xz
    46  
    47  .. note::
    48  
    49     Cilium integration, as presented in this Getting Started Guide, has
    50     been tested with Kubernetes releases 1.14, 1.15, 1.16, 1.17, and
    51     1.18. Note that this does *not* work with K8s 1.13.
    52  
    53  Deploy the default Istio configuration profile onto Kubernetes:
    54  
    55  ::
    56  
    57      ./cilium-istioctl manifest apply -y
    58  
    59  Add a namespace label to instruct Istio to automatically inject Envoy sidecar proxies when you deploy your application later:
    60  
    61  ::
    62  
    63      kubectl label namespace default istio-injection=enabled
    64  
    65  Step 3: Deploy the Bookinfo Application V1
    66  ==========================================
    67  
    68  Now that we have Cilium and Istio deployed, we can deploy version
    69  ``v1`` of the services of the `Istio Bookinfo sample application
    70  <https://istio.io/docs/examples/bookinfo.html>`_.
    71  
    72  While the upstream `Istio Bookinfo Application example for Kubernetes
    73  <https://istio.io/docs/examples/bookinfo/#if-you-are-running-on-kubernetes>`_
    74  deploys multiple versions of the Bookinfo application at the same time,
    75  here we first deploy only the version 1.
    76  
    77  The BookInfo application is broken into four separate microservices:
    78  
    79  - *productpage*. The productpage microservice calls the details and
    80    reviews microservices to populate the page.
    81  - *details*. The details microservice contains book information.
    82  - *reviews*. The reviews microservice contains book reviews. It also
    83    calls the ratings microservice.
    84  - *ratings*. The ratings microservice contains book ranking
    85    information that accompanies a book review.
    86  
    87  In this demo, each specific version of each microservice is deployed
    88  into Kubernetes using separate YAML files which define:
    89  
    90  - A Kubernetes Service.
    91  - A Kubernetes Deployment specifying the microservice's pods, specific
    92    to each service version.
    93  - A Cilium Network Policy limiting the traffic to the microservice,
    94    specific to each service version.
    95  
    96  .. image:: images/istio-bookinfo-v1.png
    97     :scale: 75 %
    98     :align: center
    99  
   100  To deploy the application with manual sidecar injection, run:
   101  
   102  .. parsed-literal::
   103  
   104      for service in productpage-service productpage-v1 details-v1 reviews-v1; do \\
   105            kubectl apply -f \ |SCM_WEB|\/examples/kubernetes-istio/bookinfo-${service}.yaml ; done
   106  
   107  Check the progress of the deployment (every service should have an
   108  ``AVAILABLE`` count of ``1``):
   109  
   110  ::
   111  
   112      watch "kubectl get deployments"
   113      NAME             READY   UP-TO-DATE   AVAILABLE   AGE
   114      details-v1       1/1     1            1           12s
   115      productpage-v1   1/1     1            1           13s
   116      reviews-v1       1/1     1            1           12s
   117  
   118  .. only:: not (epub or latex or html)
   119  
   120     Notes for Istio debugging:
   121     - Set istio proxy to debug or trace mode:
   122     kubectl exec -it $(kubectl get pod -l app=productpage -o jsonpath='{.items[0].metadata.name}') -c istio-proxy -- curl -XPOST http://127.0.0.1:15000/logging?level=debug
   123     - Check that bpf is mounted:
   124     kubectl exec -it $(kubectl get pod -l app=productpage -o jsonpath='{.items[0].metadata.name}') -c istio-proxy -- ls -la /sys/fs/bpf/tc/globals
   125     - Upgrade cilium to a local image (after setting image pull policy to never):
   126     export CILIUM_TAG=my-test-tag
   127     docker save cilium/cilium:${CILIUM_TAG} -o cilium-${CILIUM_TAG}.tar
   128     scp -i $(minikube ssh-key) cilium-${CILIUM_TAG}.tar docker@$(minikube ip):.
   129     minikube ssh "docker image load -i cilium-${CILIUM_TAG}.tar"
   130     kubectl -n kube-system set image daemonset/cilium cilium-agent=docker.io/cilium/cilium:${CILIUM_TAG}
   131  
   132  Create an Istio ingress gateway for the productpage service:
   133  
   134  .. parsed-literal::
   135  
   136      kubectl apply -f \ |SCM_WEB|\/examples/kubernetes-istio/bookinfo-gateway.yaml
   137  
   138  To obtain the URL to the frontend productpage service, run:
   139  
   140  ::
   141  
   142      export GATEWAY_URL=http://$(minikube ip):$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
   143      export PRODUCTPAGE_URL=${GATEWAY_URL}/productpage
   144      open ${PRODUCTPAGE_URL}
   145  
   146  Open that URL in your web browser and check that the application has
   147  been successfully deployed.  It may take several seconds before all
   148  services become accessible in the Istio service mesh, so you may have
   149  have to reload the page.
   150  
   151  Step 4: Canary and Deploy the Reviews Service V2
   152  ================================================
   153  
   154  We will now deploy version ``v2`` of the ``reviews`` service.  In
   155  addition to providing reviews from readers, ``reviews v2`` queries a
   156  new ``ratings`` service for book ratings, and displays each rating as
   157  1 to 5 black stars.
   158  
   159  As a precaution, we will use Istio's service routing feature to canary
   160  the ``v2`` deployment to prevent breaking the end-to-end application
   161  completely if it is faulty.
   162  
   163  Before deploying ``v2``, to prevent any traffic from being routed to
   164  it for now, we will create this Istio route rules to route 100% of the
   165  ``reviews`` traffic to ``v1``:
   166  
   167  .. literalinclude:: ../../examples/kubernetes-istio/route-rule-reviews-v1.yaml
   168  
   169  .. image:: images/istio-bookinfo-reviews-v2-route-to-v1.png
   170     :scale: 75 %
   171     :align: center
   172  
   173  Apply this route rule:
   174  
   175  .. parsed-literal::
   176  
   177      kubectl apply -f \ |SCM_WEB|\/examples/kubernetes-istio/route-rule-reviews-v1.yaml
   178  
   179  Deploy the ``ratings v1`` and ``reviews v2`` services:
   180  
   181  .. parsed-literal::
   182  
   183      for service in ratings-v1 reviews-v2; do \\
   184            kubectl apply -f \ |SCM_WEB|\/examples/kubernetes-istio/bookinfo-${service}.yaml ; done
   185  
   186  Check the progress of the deployment (every service should have an
   187  ``AVAILABLE`` count of ``1``):
   188  
   189  ::
   190  
   191      watch "kubectl get deployments"
   192      NAME             READY   UP-TO-DATE   AVAILABLE   AGE
   193      details-v1       1/1     1            1           17m
   194      productpage-v1   1/1     1            1           17m
   195      ratings-v1       1/1     1            1           69s
   196      reviews-v1       1/1     1            1           17m
   197      reviews-v2       1/1     1            1           68s
   198  
   199  Check in your web browser that no stars are appearing in the Book
   200  Reviews, even after refreshing the page several times.  This indicates
   201  that all reviews are retrieved from ``reviews v1`` and none from
   202  ``reviews v2``.
   203  
   204  .. image:: images/istio-bookinfo-reviews-v1.png
   205     :scale: 50 %
   206     :align: center
   207  
   208  The ``ratings-v1`` CiliumNetworkPolicy explicitly whitelists access
   209  to the ``ratings`` API only from ``productpage`` and ``reviews v2``:
   210  
   211  .. literalinclude:: ../../examples/kubernetes-istio/bookinfo-ratings-v1-policy.yaml
   212  
   213  Check that ``reviews v1`` may not be able to access the ``ratings``
   214  service, even if it were compromised or suffered from a bug, by
   215  running ``curl`` from within the pod:
   216  
   217  .. note::
   218  
   219     All traffic from ``reviews v1`` to ``ratings`` is blocked, so the
   220     connection attempt fails after the connection timeout.
   221  
   222  ::
   223  
   224      export POD_REVIEWS_V1=`kubectl get pods -l app=reviews,version=v1 -o jsonpath='{.items[0].metadata.name}'`
   225      kubectl exec ${POD_REVIEWS_V1} -c istio-proxy -ti -- curl --connect-timeout 5 --fail http://ratings:9080/ratings/0
   226      curl: (28) Connection timed out after 5001 milliseconds
   227      command terminated with exit code 28
   228  
   229  Update the Istio route rule to send 50% of ``reviews`` traffic to
   230  ``v1`` and 50% to ``v2``:
   231  
   232  .. literalinclude:: ../../examples/kubernetes-istio/route-rule-reviews-v1-v2.yaml
   233  
   234  .. image:: images/istio-bookinfo-reviews-v2-route-to-v1-and-v2.png
   235     :scale: 75 %
   236     :align: center
   237  
   238  Apply this route rule:
   239  
   240  .. parsed-literal::
   241  
   242      kubectl apply -f \ |SCM_WEB|\/examples/kubernetes-istio/route-rule-reviews-v1-v2.yaml
   243  
   244  Check in your web browser that stars are appearing in the Book Reviews
   245  roughly 50% of the time.  This may require refreshing the page for a
   246  few seconds to observe.  Queries to ``reviews v2`` result in reviews
   247  containing ratings displayed as black stars:
   248  
   249  .. image:: images/istio-bookinfo-reviews-v2.png
   250     :scale: 50 %
   251     :align: center
   252  
   253  Finally, update the route rule to send 100% of ``reviews`` traffic to
   254  ``v2``:
   255  
   256  .. literalinclude:: ../../examples/kubernetes-istio/route-rule-reviews-v2.yaml
   257  
   258  .. image:: images/istio-bookinfo-reviews-v2-route-to-v2.png
   259     :scale: 75 %
   260     :align: center
   261  
   262  Apply this route rule:
   263  
   264  .. parsed-literal::
   265  
   266      kubectl apply -f \ |SCM_WEB|\/examples/kubernetes-istio/route-rule-reviews-v2.yaml
   267  
   268  Refresh the product page in your web browser several times to verify
   269  that stars are now appearing in the Book Reviews on every page
   270  refresh.  All the reviews are now retrieved from ``reviews v2`` and
   271  none from ``reviews v1``.
   272  
   273  Step 5: Deploy the Product Page Service V2
   274  ==========================================
   275  
   276  We will now deploy version ``v2`` of the ``productpage`` service,
   277  which brings two changes:
   278  
   279  - It is deployed with a more restrictive CiliumNetworkPolicy, which
   280    restricts access to a subset of the HTTP URLs, at Layer-7.
   281  - It implements a new authentication audit log into Kafka.
   282  
   283  .. image:: images/istio-bookinfo-productpage-v2-kafka.png
   284     :scale: 75 %
   285     :align: center
   286  
   287  The policy for ``v1`` currently allows read access to the full HTTP
   288  REST API, under the ``/api/v1`` HTTP URI path:
   289  
   290  - ``/api/v1/products``: Returns the list of books and their details.
   291  - ``/api/v1/products/<id>``: Returns details about a specific book.
   292  - ``/api/v1/products/<id>/reviews``: Returns reviews for a specific
   293    book.
   294  - ``/api/v1/products/<id>/ratings``: Returns ratings for a specific
   295    book.
   296  
   297  Check that the full REST API is currently accessible in ``v1`` and
   298  returns valid JSON data:
   299  
   300  ::
   301  
   302      for APIPATH in /api/v1/products /api/v1/products/0 /api/v1/products/0/reviews /api/v1/products/0/ratings; do echo ; curl -s -S "${GATEWAY_URL}${APIPATH}" ; echo ; done
   303  
   304  
   305  The output will be similar to this:
   306  
   307  ::
   308  
   309      [{"descriptionHtml": "<a href=\"https://en.wikipedia.org/wiki/The_Comedy_of_Errors\">Wikipedia Summary</a>: The Comedy of Errors is one of <b>William Shakespeare's</b> early plays. It is his shortest and one of his most farcical comedies, with a major part of the humour coming from slapstick and mistaken identity, in addition to puns and word play.", "id": 0, "title": "The Comedy of Errors"}]
   310  
   311      {"publisher": "PublisherA", "language": "English", "author": "William Shakespeare", "id": 0, "ISBN-10": "1234567890", "ISBN-13": "123-1234567890", "year": 1595, "type": "paperback", "pages": 200}
   312  
   313      {"reviews": [{"reviewer": "Reviewer1", "rating": {"color": "black", "stars": 5}, "text": "An extremely entertaining play by Shakespeare. The slapstick humour is refreshing!"}, {"reviewer": "Reviewer2", "rating": {"color": "black", "stars": 4}, "text": "Absolutely fun and entertaining. The play lacks thematic depth when compared to other plays by Shakespeare."}], "id": "0"}
   314  
   315      {"ratings": {"Reviewer2": 4, "Reviewer1": 5}, "id": 0}
   316  
   317  We realized that the REST API to get the book reviews and ratings was
   318  meant only for consumption by other internal services, and will be
   319  blocked from external clients using the updated Layer-7
   320  CiliumNetworkPolicy in ``productpage v2``, i.e. only the
   321  ``/api/v1/products`` and ``/api/v1/products/<id>`` HTTP URLs will be
   322  whitelisted:
   323  
   324  .. literalinclude:: ../../examples/kubernetes-istio/bookinfo-productpage-v2-policy.yaml
   325  
   326  Because ``productpage v2`` sends messages into Kafka, we must first
   327  deploy a Kafka broker:
   328  
   329  .. parsed-literal::
   330  
   331      kubectl apply -f \ |SCM_WEB|\/examples/kubernetes-istio/kafka-v1-destrule.yaml
   332  
   333  .. parsed-literal::
   334  
   335      kubectl apply -f \ |SCM_WEB|\/examples/kubernetes-istio/kafka-v1.yaml
   336  
   337  Wait until the ``kafka-v1-0`` pod is ready, i.e. until it has a
   338  ``READY`` count of ``1/1``:
   339  
   340  ::
   341  
   342      watch "kubectl get pods -l app=kafka"
   343      NAME         READY     STATUS    RESTARTS   AGE
   344      kafka-v1-0   1/1       Running   0          21m
   345  
   346  Create the ``authaudit`` Kafka topic, which will be used by
   347  ``productpage v2``:
   348  
   349  ::
   350  
   351      kubectl exec kafka-v1-0 -c kafka -- bash -c '/opt/kafka_2.11-0.10.1.0/bin/kafka-topics.sh --zookeeper localhost:2181/kafka --create --topic authaudit --partitions 1 --replication-factor 1'
   352  
   353  We are now ready to deploy ``productpage v2``.
   354  
   355  Create the ``productpage v2`` service and its updated
   356  CiliumNetworkPolicy and delete ``productpage v1``:
   357  
   358  .. parsed-literal::
   359  
   360      kubectl apply -f \ |SCM_WEB|\/examples/kubernetes-istio/bookinfo-productpage-v2.yaml
   361  
   362  .. parsed-literal::
   363  
   364      kubectl delete -f \ |SCM_WEB|\/examples/kubernetes-istio/bookinfo-productpage-v1.yaml
   365  
   366  ``productpage v2`` implements an authorization audit logging.  On
   367  every user login or logout, it produces into Kafka topic ``authaudit``
   368  a JSON-formatted message which contains the following information:
   369  
   370  - event: ``login`` or ``logout``
   371  - username
   372  - client IP address
   373  - timestamp
   374  
   375  To observe the Kafka messages sent by ``productpage``, we will run an
   376  additional ``authaudit-logger`` service.  This service fetches and
   377  prints out all messages from the ``authaudit`` Kafka topic.  Start
   378  this service:
   379  
   380  .. parsed-literal::
   381  
   382      kubectl apply -f \ |SCM_WEB|\/examples/kubernetes-istio/authaudit-logger-v1.yaml
   383  
   384  Check the progress of the deployment (every service should have an
   385  ``AVAILABLE`` count of ``1``):
   386  
   387  ::
   388  
   389      watch "kubectl get deployments"
   390      NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
   391      authaudit-logger-v1   1/1     1            1           41s
   392      details-v1            1/1     1            1           37m
   393      productpage-v2        1/1     1            1           4m47s
   394      ratings-v1            1/1     1            1           20m
   395      reviews-v1            1/1     1            1           37m
   396      reviews-v2            1/1     1            1           20m
   397  
   398  Check that the product REST API is still accessible, and that Cilium
   399  now denies at Layer-7 any access to the reviews and ratings REST API:
   400  
   401  ::
   402  
   403      for APIPATH in /api/v1/products /api/v1/products/0 /api/v1/products/0/reviews /api/v1/products/0/ratings; do echo ; curl -s -S "${GATEWAY_URL}${APIPATH}" ; echo ; done
   404  
   405  The output will be similar to this:
   406  
   407  ::
   408  
   409      [{"descriptionHtml": "<a href=\"https://en.wikipedia.org/wiki/The_Comedy_of_Errors\">Wikipedia Summary</a>: The Comedy of Errors is one of <b>William Shakespeare's</b> early plays. It is his shortest and one of his most farcical comedies, with a major part of the humour coming from slapstick and mistaken identity, in addition to puns and word play.", "id": 0, "title": "The Comedy of Errors"}]
   410  
   411      {"publisher": "PublisherA", "language": "English", "author": "William Shakespeare", "id": 0, "ISBN-10": "1234567890", "ISBN-13": "123-1234567890", "year": 1595, "type": "paperback", "pages": 200}
   412  
   413      Access denied
   414  
   415  
   416      Access denied
   417  
   418  This demonstrated that requests to the
   419  ``/api/v1/products/<id>/reviews`` and
   420  ``/api/v1/products/<id>/ratings`` URIs now result in Cilium returning
   421  ``HTTP 403 Forbidden`` HTTP responses.
   422  
   423  Every login and logout on the product page will result in a line in
   424  this service's log. Note that you need to log in/out using the ``sign
   425  in``/``sign out`` element on the bookinfo web page. When you do, you
   426  can observe these kind of audit logs:
   427  
   428  ::
   429  
   430      export POD_LOGGER_V1=`kubectl get pods -l app=authaudit-logger,version=v1 -o jsonpath='{.items[0].metadata.name}'`
   431  
   432  ::
   433  
   434      kubectl logs ${POD_LOGGER_V1} -c authaudit-logger
   435      ...
   436      {"timestamp": "2017-12-04T09:34:24.341668", "remote_addr": "10.15.28.238", "event": "login", "user": "richard"}
   437      {"timestamp": "2017-12-04T09:34:40.943772", "remote_addr": "10.15.28.238", "event": "logout", "user": "richard"}
   438      {"timestamp": "2017-12-04T09:35:03.096497", "remote_addr": "10.15.28.238", "event": "login", "user": "gilfoyle"}
   439      {"timestamp": "2017-12-04T09:35:08.777389", "remote_addr": "10.15.28.238", "event": "logout", "user": "gilfoyle"}
   440  
   441  As you can see, the user-identifiable information sent by
   442  ``productpage`` in every Kafka message is sensitive, so access to this
   443  Kafka topic must be protected using Cilium.  The CiliumNetworkPolicy
   444  configured on the Kafka broker enforces that:
   445  
   446  - only ``productpage v2`` is allowed to produce messages into the
   447    ``authaudit`` topic;
   448  - only ``authaudit-logger`` can fetch messages from this topic;
   449  - no service can access any other topic.
   450  
   451  .. literalinclude:: ../../examples/kubernetes-istio/kafka-v1-policy.yaml
   452  
   453  Check that Cilium prevents the ``authaudit-logger`` service from
   454  writing into the ``authaudit`` topic (enter a message followed by
   455  ENTER, e.g. ``test message``)
   456  
   457  .. note::
   458  
   459     Note that the error message may take a short time to appear.
   460  
   461  .. note::
   462  
   463     You can terminate the command with a single ``<CTRL>-d``.
   464  
   465  ::
   466  
   467      kubectl exec ${POD_LOGGER_V1} -c authaudit-logger -ti -- /opt/kafka_2.11-0.10.1.0/bin/kafka-console-producer.sh --broker-list=kafka:9092 --topic=authaudit
   468      test message
   469      [2017-12-07 02:13:47,020] ERROR Error when sending message to topic authaudit with key: null, value: 12 bytes with error: (org.apache.kafka.clients.producer.internals.ErrorLoggingCallback)
   470      org.apache.kafka.common.errors.TopicAuthorizationException: Not authorized to access topics: [authaudit]
   471  
   472  This demonstrated that Cilium sent a response with an authorization
   473  error for any ``Produce`` request from this service.
   474  
   475  Create another topic named ``credit-card-payments``, meant to transmit
   476  highly-sensitive credit card payment requests:
   477  
   478  ::
   479  
   480      kubectl exec kafka-v1-0 -c kafka -- bash -c '/opt/kafka_2.11-0.10.1.0/bin/kafka-topics.sh --zookeeper localhost:2181/kafka --create --topic credit-card-payments --partitions 1 --replication-factor 1'
   481  
   482  Check that Cilium prevents the ``authaudit-logger`` service from
   483  fetching messages from this topic:
   484  
   485  ::
   486  
   487      kubectl exec ${POD_LOGGER_V1} -c authaudit-logger -ti -- /opt/kafka_2.11-0.10.1.0/bin/kafka-console-consumer.sh --bootstrap-server=kafka:9092 --topic=credit-card-payments
   488      [2017-12-07 03:08:54,513] WARN Not authorized to read from topic credit-card-payments. (org.apache.kafka.clients.consumer.internals.Fetcher)
   489      [2017-12-07 03:08:54,517] ERROR Error processing message, terminating consumer process:  (kafka.tools.ConsoleConsumer$)
   490      org.apache.kafka.common.errors.TopicAuthorizationException: Not authorized to access topics: [credit-card-payments]
   491      Processed a total of 0 messages
   492  
   493  This demonstrated that Cilium sent a response with an authorization
   494  error for any ``Fetch`` request from this service for any topic other
   495  than ``authaudit``.
   496  
   497  .. note::
   498  
   499     At present, the above command may also result in an error message.
   500  
   501  Step 6: Clean Up
   502  ================
   503  
   504  You have now installed Cilium and Istio, deployed a demo app, and
   505  tested both Cilium's L3-L7 network security policies and Istio's
   506  service route rules.  To clean up, run:
   507  
   508  ::
   509  
   510      minikube delete
   511  
   512  After this, you can re-run the tutorial from Step 0.