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.