Thursday, April 29, 2021

Global Warming: Time for the Nuclear Option

The last few months I have spent educating myself about global warming. I saw the documentary about Greta Thunberg and I figured that she has a point, so I decided to "Listen to the scientists".

I've read multiple books, finished a couple of Coursera courses and watched more YouTube videos than a teenager. The conclusion I have come to from all of this is that it's time to start investing heavily in nuclear power!

The one thing that we can be sure of the coming years is that we will need a lot of electrical energy. All the energy that is currently used for making steel and driving cars will need to come from electricity since only electricity can be created without producing green house gases.

Wind and solar power are great, but they cannot provide the amounts of reliable energy that will be required.

Sweden is a tiny country (#55 in the world by area). Our energy usage clocks in at around 40th place (#25 per capita). You might think that we are an important country that can make a difference on the climate.

WRONG! Sweden is an insignificant statistical blip. We use less than half a percent of the global energy. China uses about 25 percent and the US around 16 percent.

China is currently building one new coal power plant per week in China and also helping other developing countries build coal plants in exchange for political power.

How can this be? Isn't China part of the Paris agreement? Yes, but China is treated as a developing country and, in the name of fairness, doesn't have to limit it's carbon footprint. The climate doesn't care about fairness.

A Coal plant has an average lifetime of 40 years.

China is by no means the only country trying to expand their fossil fuel usage. It's all over the world!

This means that our hope of reaching the Paris agreement of keeping the temperature below 2 degrees C is inexistent.

So, what should we do? Should we just shrug and say "Fuck it, we're screwed anyway".

I don't think so. Sweden is a technologically advanced country and we can be an example. We can show the world what can be done.

What has Sweden done so far? A tax on plastic bags. For fuck sake!

There has also been other suggestions, but all of them are about the future. In Sweden, just as in every other country, politicians love to make bold promises about the future, instead of acting in the present. Promises, doesn't cost anything, but they don't improve anything either.

Almost 40% of Sweden's energy consumption is fossil-based. All of it has to become fossil-free.

This requires a lot of fossil-free energy.

HYBRIT, fossil-free steel is a really cool invention that is currently worked on by Swedish mining companies. The coal normally used in the creation of steel will be replaced by hydrogen produced by water and fossil-free energy.

This requires a lot of fossil-free energy.

Wind and solar produces less than 10% of the energy in Sweden. Currently, nuclear produces about 27%, down from 33%. This means that almost all of the carbon reductions we have achieved from building out solar and wind has been lost due to nuclear reductions.

If we instead of reducing nuclear had increased it, Sweden could have been almost carbon neutral now!

Nuclear has the smallest carbon footprint of any energy source. It's even lower that Wind and Solar.

But, what about the risk of accidents? The whole world will be contaminated if we have a nuclear meltdown. The facts tell a different story.

Chernobyl, the worst accident by far, has killed less than 60 people, to date. Fukushima has produced 1 dead due to cancer caused by radiation (most people died in the Tsunami). Three Mile Island, the accident that caused the nuclear scare in the 70s, produced zero deaths.

Nuclear power has killed less than a 100 people in 50 years.

Carbon pollution is estimated to be killing more than three million people per year.

Update: According to some models, link below, Chernobyl is expected to kill +4000 people from long term low-level radiation exposure. It doesn't invalidate my point.

When accidents have been shown to be insignificant, the elephant in the nuclear room is nuclear waste.

Nuclear waste is classified into three categories, High, Intermediate and Low Level Waste. Small parts of the High Level Waste (HLW) can stay active for 1000 years.

Only, 3 percent of waste is classified as HLW. If the waste is reprocessed, as it is in France, the amount is reduced to 0.2 percent.

According to the Nuclear Industry:

They have developed – and implemented – most of the necessary technologies required for the final disposal of all of the waste it produces. The remaining issue is one of public acceptance, and not of technological feasibility.

I don't know enough about nuclear waste storage to know if this is the case or not, but even if the waste problem is not solved, we need to move forward with Nuclear.

The experts agree that global warming based on our carbon emissions is putting future generations at risk.

The responsible thing to do it to expand the most effective way to create carbon-free energy.

The time is ripe for nuclear power.

Next time you hear someone say that we need to do this or that for the environment, ask "How?"

"How, will this make a significant impact?".

"How, will this make us carbon neutral?".

If they can't answer that, they're just wasting time.



How to avoid a climate disaster by Bill Gates This is a great book that has been criticised since Gates is a high poluter that likes to eat hamburgers instead of by the information that it contains. He clearly highlights all the challenges we are facing and does it through an economic perspective that targets business people. If you are not ecomically inclined you may see this as a drawback, but since the move to carbon-neutral must be financed I think that it is a great way to frame it.

Apocalypse Never by Michael Shellenberger Michael Shellenberger is an environmentalist that has become fed up with alarmist communication and tries to tackle many environmental problems with facts. A fantastic book! Among other things, he puts the upcoming catastrophe into perspective. It's not the end of the world.

Klimatkatastofens psykologi by Billy Larsson: Billy Larsson is a psychologist who was written a comprehensive evaluation of many the problems we are facing with climate change. The author doesn't have high hopes that we will pull through this and has started to invest in a farm to do his part to live ecologically.

This Changes Everything by Naomi Klein Noami Klein believes that global warming will force the world out of "deregulated capitalism". Even though I agree with many of the things she writes about, I don't have any hopes that this will force this change. Nevertheless, it's a good book worth reading.

Six Degrees by Mark Lynas Mark Lynas describes the effetct of Global Warming, known as "Global Weirding" as the temperature rises. It's an interesting book showing many of the worst case scenarios that may occur in the future.

Global Warming: Understanding the Forecast by David Archier This book is the litterature behind the Coursera Global Warming course, linked below. It's a in depth book about how the systems of the earth works and how the scientists can know that we are warming up the globe.

Global Warming: A Very Peculiar History A concise history of global warming.

Åtta steg mot avgrunden Another book about global weirding. One chapter per decade until the end of the century.

How to Drive a Nuclear Reactor by Colin Tucker A tour of the science behind nuclear reactors, through their start-up, operation and shutdown.


Global Warming I: The Science and Modeling of Climate Change

Global Warming II: Create Your Own Models in Python


Why renewables can’t save the planet | Michael Shellenberger

Bill Gates: The 2021 60 Minutes Interview

The Climate for Nuclear | Daniel Poneman

Why I changed my mind about nuclear power | Michael Shellenberger


Sweden: Energy Country Profile

Ten Reasons to Oppose Nuclear Energy

Radioactive Waste – Myths and Realities

What was the death toll from Chernobyl and Fukushima?

Thursday, October 29, 2020

The Corona Virus from a Tapir's Perspective

Tapir Gazette: So, what do you think about the latest conflict between the Humans and the Corona Viruses?

Tony: It's about fucking time someone fought back against those bastards. They've been bullying all other species for far too long!

Tara: Hear, hear! I've been hoping someone would take them on for years, but there seemed to be no stopping them.

Tuck: Yes, they have been eradicating the rest of us at their expense for hundreds of years now. I'm glad someone is sticking it to them. Go Corona!

Tara: The worst part is that they think they have a right to this since they are they Kings of the world. Who wears the crown (corona) now, motherfuckers!

Tapir Gazette: What about the strategy of the Corona Viruses?

Tanya: It was looking pretty good in the beginning, when the mortality rate was about 6%. That could really have made a dent in the population, perhaps enough to keep them indoors. But, now it looks like it's more 0.6% and that won't make a difference in the long run.

Tuck: I think the Coronas should have been more patient. They should have waited longer before they started taking people out and just infected as many as they could before striking.

Tanya: Yeah, I agree, they jumped the gun. It would have been better to stay under the radar for a longer time before coming out in force.

Tara: But it was a smart move to strike in the dictatorships first. It gave them more time to spread to the rest of the world since the dictatorships care more about appearances than about people.

Tapir Gazette: What about the human tactics?

Tony: From my perspective the "Shelter in Place" tactics is awesome! The more we keep the humans indoors the better it is for everyone else. But, from a human perspective, I don't know. I don't think it will last very long if the mortality rate stays below 1%.

Tuck: Humans have become so complacent, they can't handle a crisis like this. If they can't find toilet paper at the store, they riot!

Tapir Gazette: Why do you dislike the humans so much?

Tuck: What's not to dislike? They are the most speciest (racists for species) assholes on earth. They care about nothing but themselves. Even the richest, so called philanthropists, only care about helping people at the expense of the rest of us.

Tanya: Yeah, have you seen the population curves? They are totally crazy.

Tony: Yeah, they are the real pandemic!

Tapir Gazette: Any final words, anyone?

Tuck: I hope it's not my final words, but who knows these days ;). I don't think that all humans are assholes, some of them try to make a difference. The latest report from Living Planet shows that at least some people seem to care.

Tanya: I wish I had your positive mindset Tuck, but I can't see anything bright about our future. The only good human is a dead human. At least they are good fertilizers!

Note: The names of the tapirs have been changed to protect them from retaliation.

Saturday, January 04, 2020

Three Years in Silicon Valley

Three years ago, I moved with my family, wife, two kids and two dogs, from Sweden to California to work for a subsidiary of a Swedish company called Jayway Inc.

Jayway Inc. was located in Palo Alto, the heart of Silicon Valley. Silicon Valley is a wide valley that is situated between two mountain ranges, the Santa Cruz Mountains along the cost, and the Diablo Range on the other side of the bay. The area is known as "the Bay Area" to locals since the bay stretches through the whole valley from San Francisco in the north to San José in the south.

San José, the lesser know of the two cities is actually the larger of the two with a population of more than 1 million. San Francisco has around 800 thousand.


During my three years I mainly worked for Walmart and it's membership part, Sam's Club. Walmart is the largest private company in the world, both in terms of revenue, $500 billion, and in terms of employees, 2.2 million. There are two non-private organizations which have more employees than Walmart, the U.S. and the Chinese armies.

Working in a huge organization like this may be intimidating, but the teams I worked with were surprisingly nimble and we were expected to take initiatives and responsibility for what we did. There was no micro-management and, if anything, I have had to little input on what direction to move in.

The three projects I worked in were very disparate.

The first was the test tools team, where I helped out to build tools for testing mobile applications "in the cloud" with Sauce Labs and Firebase Test Lab.

My second project was a re-write of the backend for Sam's club's Scan and Go application. An application where you use your mobile phone to scan products and checkout without having to stand in line.

In my third project, I worked on Kubernetes for WCNP, the Walmart Cloud Native Platform. A cross-platform offering that allows Walmart teams to deploy their applications to GCP, Azure, and one of 5000 VM-Ware installations in the stores and distribution centers. Quite a challenge.

Leisure Time

When not working, it's possible to do anything in the Bay Area.

The mountains surrounding the bay, twenty minutes away, allows for hiking and mountain biking. On a typical trip you will see wild turkeys, coyotes and deer, and if you are really lucky, mountain lions.

On the coast, the waves are spectacular and provides among the best surfing in the world. Half Moon Bay, and Maverick's beach is host to a yearly big wave surf competition known as Titans of Mavericks.

If you are fond of climbing, Planet Granite has three climbing centers in the bay area and if you want to climb outdoors, Yosemite National Park is less than 4 hours away. I recommend watching "Valley Uprising" and "Free Solo" before you go.

There is also iFly if you want to learn how to skydive in a wind tunnel or a number of small private airports if you want to take flying lessons.

For skiing, Lake Tahoe is 4 hours away, depending on traffic. Our longest trip took 12 hours.

Lake Tahoe holds a number of skiing resorts. During our time in the states we tried out Heavenly, Kirkwood, North Star and Squaw Valley. They were all good for different reasons.


Traffic is awful! The 101, a 5 lane highway through the heart of the valley is congested during rush hours. Rush hours are between 7 and 10 in the morning and 4 through 7 in the afternoon. At this time it will take you at least twice as long as it normally does to go from one place to another. This means it will take two hours to go from San José to San Francisco, if there are no accidents!

The 101 is also far from a safe highway. Many places have potholes the size of a tire and if you are not paying attention you may easily get a flat.

Taking trips to Tahoe or Yosemite on popular times, such as the weekend, will also take you a long time even if the weather conditions are good. If it's a snow storm, forgettaboutit!

One way to speed up your travel is to use the car pool lanes. This is one or two lanes that are dedicated to people with two or more people in it. This helps, but since you may also use it if you drive an electric car, in the area where there is most Tesla's per capita, it doesn't help much.

And since this is the U.S. of A., there is another solution, Pay for it. In many areas, the car pool lane has been replaced with a Fast-Track lane, it allows you to pay to use the lane and the price depends on what time of day you are driving. Why should the rich have to wait for poor people? That is just silly!

Americans also drive differently than Swedes. Many drivers choose one of the lanes and then stick to that lane for the entire trip, no matter what speed they are going. It's quite a contrast to Sweden where the left lanes are used for passing and you normally drive in the right-most lane.


Caltrain is a train that runs through the entire valley, from SF in the north all the way down to Gilroy in the south. It is diesel powered and feels very dated compared to the Swedish trains. The road crossings are amazingly stupid. Most are in the same plane as the roads and often have a traffic light on the other side of the track with room for one car. It is easy to become stuck on the tracks when the lights switch to red. A lot of accidents has happened because of this.

Not everything is bad about the trains though. The cars have two floors and can fit quite a lot of people. But, the best part is the bicycle cars. These are cars where the lower floor is for bicycles and they take around 40 per car. This is awesome and better than anything I have seen anywhere in Europe.

The bikes are stacked along the walls and the loading and packing is managed by the riders. It is simplified by most bikes having a label describing its destination.


Everything costs money here. A membership in the YMCA, one of the cheaper training facilities, costs about $80 a month. If you want to go to a more fancy place, it can easily set you back $250 a month.

Lunch at an okay restaurant will cost you about $15 with water to drink and no tip included. The normal tip for food and drink is 18 percent. Tipping at a service facility such as a massage parlor is 20 to 25 percent. Get used to it. That's how it works here.

But, if you spend money, you can buy anything. There are wineries and breweries everywhere, not just in Napa and Sonoma. Want to smoke some weed? Just go to any of the local dispensaries or have it delivered to your door. Cannabis is legal in California for both medical and recreational use!

What else can you have delivered? Any food can be delivered by DoorDash, GrubHub, UberEats or any of tens of other delivery services.

Want to have yourself delivered? Order an Uber or a Lyft and you will have a car at your door in less than five minutes that takes you where you want to go. It even works at 5 in the morning when you need to catch an early flight.

Going to the doctor or dentist may also cost you if you are not paying attention. Even though the Jayway insurance was really good, a doctor may still (a dentist will definitely) suggest that you get a procedure that is not included. Always ask "Is it included in my insurance?" before you say yes to anything.

Health Care

The health care system is very good, if you have good insurance. The health care providers I was in contact with had very short access times and it was easy to an appointment. They were also proactive and scheduled a variety of different checkups to help me stay aware of my health.

In Sweden this is not the case. Most people go to the doctor when they are sick and not to prevent you from becoming sick.

When I go to a doctor in Sweden, I would say that they will take the minimum amount of tests that they think are required. In the US, it felt like the opposite was true. A lot of tests seemed to be taken that were not strictly necessary, but they could be motivated and they will profit the hospital and thus were taken.

This may be good for you as a patient, but it is not good for society as a whole since it is wasteful and will increase the overall cost.

Schools and Kids

The schools that my kids attended were awesome. They are ranked as some of the best public schools in the country and when I compare it to the schools that I went to when I was young, both in Sweden and in the U.S., it is fantastic. The students are motivated and so are the teachers. My son, who didn't do much in school in Sweden, did his homework without any interference from us. Talk about positive peer pressure. Even though the schools are technically free, you are expected to give a voluntary donation of $500 per child and year.

Sport as part of the school activities is free(ish), but if your kids want sports outside of school, they have to join a club. The clubs are great, but expensive. My daughter's diving practice has an Olympic coach from Ukraine, they practice 6 days a week and it costs us $550 a month and nothing except training is included! For comparison, her Swedish club, costs about 600 SEK ($60) a year and travel to all competitions is included.


If you ever been in contact with a U.S. Government you know why so many Americans are republicans. Any contact with DMV or IRS makes you want to kill yourself. The only reason there aren't any DMV shootings in the United States is, because they have a metal detector when you enter their facilities. People probably go and shoot up the nearest school after their latest Governmental visit.

As if visiting a Governmental office in person is not bad enough, their telephone service is beyond bad. Imagine a telephone service where you are supposed to talk to the service instead of pressing buttons. The service is configured in deaf grand-mother mode and again you are looking for your gun!

Watching the following DMV scene from Zootopia will give you a rough idea, but reality is worse.


The weather in the Bay area is typically sunny from the beginning of April to the end of October. This is quite a treat for a Swede! It's nice to be able to plan a hike or a BBQ for next week without having to worry about rain!

But, the weather varies a lot from place to place. The temperature in the south bay can be a lot warmer than the weather on the coast or in San Francisco. I once drove from 90 degrees (30C) in Saratoga to 60 degrees (15C) in San Francisco. It taught me to always carry an extra jacket in my car.

I'll end this with a sunny day at the Sonoma Raceway, you can see the beginnings of the Sonoma and Napa valleys in the background.

Monday, October 22, 2018

Understanding Istio Ingress Gateway in Kubernetes

Traditionally, Kubernetes has used an Ingress controller to handle the traffic that enters the cluster from the outside. When using Istio, this is no longer the case. Istio has replaced the familiar Ingress resource with new Gateway and VirtualServices resources. They work in tandem to route the traffic into the mesh. Inside the mesh there is no need for Gateways since the services can access each other by a cluster local service name.

So how does it work? How does a request reach the application it wants? It is more complicated than one would think. Here is a drawing and a quick overview.

  1. A client makes a request on a specific port.
  2. The Load Balancer listens on this port and forwards the request to one of the workers in the cluster (on the same or a new port).
  3. Inside the cluster the request is routed to the Istio IngressGateway Service which is listening on the port the load balancer forwards to.
  4. The Service forwards the request (on the same or a new port) to an Istio IngressGateway Pod (managed by a Deployment).
  5. The IngressGateway Pod is configured by a Gateway (!) and a VirtualService.
  6. The Gateway configures the ports, protocol, and certificates.
  7. The VirtualService configures routing information to find the correct Service
  8. The Istio IngressGateway Pod routes the request to the application Service.
  9. And finally, the application Service routes the request to an application Pod (managed by a deployment).

Routing a Request through Istio Gateway to an Application

The Load Balancer

The load balancer can be configured manually or automatically through the service type: LoadBalancer. In this case, since not all clouds support automatic configuration, I'm assuming that the load balancer is configured manually to forward traffic to a port that the IngressGateway Service is listening on. Manual load balancers don't communicate with the cluster to find out where the backing pods are running, and we must expose the Service with type: NodePort and they are only available on high ports, 30000-32767. Our LB is listening on the following ports.

  • HTTP - Port 80, forwards traffic to port 30080.
  • HTTPS - Port 443, forwards traffic to port 30443.
  • MySQL - Port 3306, forwards traffic to port 30306.

Make sure your load balancer configuration forwards to all your worker nodes. This will ensure that the traffic gets forwarded even if some nodes are down.

The IngressGateway Service

The IngressGateway Service must listen to all the above ports to be able to forward the traffic to the IngressGateway pods. We use the routing to bring the port numbers back to their default numbers.

Please note that a Kubernetes Service is not a "real" service, but, since we are using type: NodePort, the request will be handled by the kube-proxy provided by Kubernetes and forwarded to a node with a running pod. Once on the node, an IP-tables configuration will forward the request to the appropriate pod.

# From the istio-ingressgateway service
  - name: http2
    nodePort: 30000
    port: 80
    protocol: TCP
  - name: https
    nodePort: 30443
    port: 443
    protocol: TCP
  - name: mysql
    nodePort: 30306
    port: 3306
    protocol: TCP

If you inspect the service, you will see that it defines more ports than I have describe above. These ports are used for internal Istio communication.

The IngressGateway Deployment

Now we have reached the most interesting part in this flow, the IngressGateway. This is a fancy wrapper around the Envoy proxy and it is configured in the same way as the sidecars used inside the service mesh (it is actually the same container). When we create or change a Gateway or VirtualService, the changes are detected by the Istio Pilot controller which converts this information to an Envoy configuration and sends it to the relevant proxies, including the Envoy inside the IngressGateway.

Don't confuse the IngressGateway with the Gateway resource. The Gateway resource is used to configure the IngressGateway

Since container ports don't have to be declared in Kubernetes pods or deployments, we don't have to declare the ports in the IngressGateway Deployment. But, if you look inside the deployment you can see that there are a number of ports declared anyway (unnecessarily).

What we do have to care about in the IngressGateway Deployment is SSL certificates. To be able to access the certificates inside the Gateway resources, make sure that you have mounted the certificates properly.

# Example certificate volume mounts
- mountPath: /etc/istio/ingressgateway-certs
  name: ingressgateway-certs
  readOnly: true
- mountPath: /etc/istio/ingressgateway-ca-certs
  name: ingressgateway-ca-certs
  readOnly: true

# Example certificate volumes
- name: ingressgateway-certs
    defaultMode: 420
    optional: true
    secretName: istio-ingressgateway-certs
- name: ingressgateway-ca-certs
    defaultMode: 420
    optional: true
    secretName: istio-ingressgateway-ca-certs

The Gateway

The Gateway resources are used to configure the ports for Envoy. Since we have exposed three ports with the service, we need these ports to be handled by Envoy. We can do this by declaring one or more Gateways. In my example, I'm going to use a single Gateway, but it may be split into two or three.

kind: Gateway
  name: default-gateway
  namespace: istio-system
    istio: ingressgateway

  - hosts:
    - '*'
      name: http
      number: 80
      protocol: HTTP

  - hosts:
    - '*'
      name: https
      number: 443
      protocol: HTTPS
      mode: SIMPLE
      privateKey: /etc/istio/ingressgateway-certs/tls.key
      serverCertificate: /etc/istio/ingressgateway-certs/tls.crt

  - hosts: # For TCP routing this fields seems to be ignored, but it is matched
    - '*'  # with the VirtualService, I use * since it will match anything.
      name: mysql
      number: 3306
      protocol: TCP

Valid ports are, HTTP|HTTPS|GRPC|HTTP2|MONGO|TCP|TLS. More info about Gateways can be found in the Istio Gateway docs

The VirtualService

Our final interesting resource is the VirtualService, it works in concert with the Gateway to configure Envoy. If you only add a Gateway nothing will show up in the Envoy configuration, and the same is true if you only add a VirtualService.

VirtualServices are really powerful and they enable the intelligent routing that is one of the very reasons we want to use Istio in the first place. However, I'm not going into it in this article since it is about the basic networking and not the fancy stuff.

Here's a basic configuration for an HTTP(s) service.

kind: VirtualService
  name: counter
  - default-gateway.istio-system.svc.cluster.local
  - match:
    - uri:
      prefix: /
    - destination:
        host: counter
          number: 80

Now, when we have added both a Gateway and a VirtualService, the routes have been created in the Envoy configuration. To see this, you can kubectl port-forward istio-ingressgateway-xxxx-yyyy 15000 and check out the configuration by browsing to http://localhost:15000/config_dump.

Note that the gateway specified as well as the host must match the information in the Gateway. If it doesn't the entry will not show up in the configuration.

// Example of http route in Envoy config
  name: "counter:80",
  domains: [
  routes: [
      match: {
        prefix: "/"
      route: {
        cluster: "outbound|80||counter.default.svc.cluster.local",
        timeout: "0s",
        max_grpc_timeout: "0s"

Here's a basic configuration for a TCP service.

kind: VirtualService
  name: mysql
  - default-gateway.istio-system.svc.cluster.local
  hosts: # The host fields seems to only be used to match the Gateway.
  - '*' # I'm using '*', the listener created is listing on
  - match:
      - port: 3306
    - destination:
        host: mysql.default.svc.cluster.local
          number: 3306

This will result in a completely different configuration in the Envoy config.

listener: {
  name: "",
  address: {
    socket_address: {
      address: "",
      port_value: 3306

Application Service and Deployment

Our request have now reached the application service and deployment. These are just normal Kubernetes resources and I will assume that if you have read this far, you already know all about it. :)


Debugging networking issues can be difficult at times, so here are some aliases that I find useful.

Debugging networking issues can be difficult at times, so here are some aliases that I find useful.

# Port forward to the first istio-ingressgateway pod
alias igpf='kubectl -n istio-system port-forward $(kubectl -n istio-system
get pods -listio=ingressgateway -o=jsonpath="{.items[0]}") 15000'

# Get the http routes from the port-forwarded ingressgateway pod (requires jq)
alias iroutes='curl --silent http://localhost:15000/config_dump |
jq '\''.configs.routes.dynamic_route_configs[].route_config.virtual_hosts[]|
{name: .name, domains: .domains, route: .routes[].match.prefix}'\'''

# Get the logs of the first istio-ingressgateway pod
# Shows what happens with incoming requests and possible errors
alias igl='kubectl -n istio-system logs $(kubectl -n istio-system get pods
-listio=ingressgateway -o=jsonpath="{.items[0]}") --tail=300'

# Get the logs of the first istio-pilot pod
# Shows issues with configurations or connecting to the Envoy proxies
alias ipl='kubectl -n istio-system logs $(kubectl -n istio-system get pods
-listio=pilot -o=jsonpath="{.items[0]}") discovery --tail=300'

When you have started the port-forwarding to the istio-ingressgateway, with igpf, here are some more things you can do.


Networking with Kubernetes and Istio is far from trivial, hopefully this article has shed some light on how it works. Here are some key takeaways.

To Add a New Port to the IngressGateway

  • Add the port to an existing Gateway or configure a new.
  • If it's a TCP service also add the port to the VirtualService, not needed for HTTP since it matches on layer 7 (domain name, etc.).
  • Add the port to the ingressgateway service. If you are using service type: LoadBalancer, you are done.
  • Otherwise, open the port in the load balancer and forward traffic to all worker nodes.

To Add Certificates to an SSL Service

  • Add the TLS secrets to the cluster.
  • Mount the secret volumes in the ingressgateway.
  • Configure the Gateway to use the newly created secrets.

Sunday, March 12, 2017

A Short Introduction to Makefiles

Makefiles are really good at one thing, managing dependencies between files. In other words, make makes sure all files that depend on another file are updated when that file changes.

We tell make how to do this by declaring rules. A typical rule looks like this:

A Simple Makefile

# Makefile
# Create bundle.js by concatenating jquery.js lib.js and main.js
bundle.js: jquery.js lib.js main.js
 cat $^ > $@

There are three parts to this rule:

  • The target, bundle.js, before the colon (:).
  • The prerequisites (what the target depends on), jquery.js lib.js main.js, after the colon (:).
  • The command, cat $^ > $@, on the next line after a leading tab, (\t).

There are two "automatic" variables in this command.

  • $@ - filename representing the target, in this case bundle.js.
  • $^ - filenames representing the list of the prerequisites (with duplicates removed).

"Automatic" means that the variables are automatically populated with relevant filenames. This will make more sense when we get into patterns later.

Here are some more variables that are useful.

  • $< - filename representing the first prerequisite.
  • $? - filenames representing the list of the prerequisites that are newer than the target.
  • $* - filename representing the stem of the target, in the above case bundle.

The Make Manual contains the full list of automatic variables


Running make with the above Makefile results in the following execution.

$ make
cat jquery.js lib.js main.js > bundle.js

$ make
make: 'bundle.js' is up to date.

make runs the first target it finds in the file if none is given on the command line. In this case it is the only target.

The second run didn't do anything since bundle.js is up to date. To be up to date means that the last-modified time of bundle.js is newer than any of its prerequisites' last-modified times. Simple but powerful! When we create new targets all we have to worry about is making sure that our targets know what files it depends on, and what files they depend on, and so on.

It is possible to enter many targets on the left of the colon (:). make will treat them as separate rules and the automatic variable will make sure that the correct files are built.

But, since make treats the rules as separate rules, it will only build the first of them, the default target.

# Makefile
bundle.js bundle2.js: jquery.js lib.js main.js
 cat $^ > $@
$ make
make: 'bundle.js' is up to date.

If we want to build bundle2.js, we can do it by explicitly telling make to do it by giving the target as command line parameter.

$ make bundle2.js
cat jquery.js lib.js main.js > bundle2.js

To get make to build both targets at once, we need to add a new, .PHONY:, target.

# Makefile
.PHONY: bundles
bundles: bundle.js bundle2.js

bundle.js bundle2.js: jquery.js lib.js main.js
 cat $^ > $@

Running make now results in (after removing bundle*)

$ make
cat jquery.js lib.js main.js > bundle.js
cat jquery.js lib.js main.js > bundle2.js

A .PHONY: target is a target without a corresponding file for make to check last modified time on. This means the target will always be run, forcing make to check if all the target's prerequisites needs to be built. The .PHONY label is not strictly necessary. If it is left out, make will check to see if there is a file called bundles and since there isn't one it will build it anyway.

Here's an illustration:

# Makefile
 echo 'Running build'
# Makefile2
 echo 'Running build'
$ touch build
$ make
make: 'build' is up to date.
$ make -f Makefile2
echo 'Running build'

Marking a target that doesn't represent a file as .PHONY: is easy to do and avoids annoying problems once your Makefile grows.

.PHONY: clean

Conventionally every Makefile contains a clean target to remove all the artifacts that are built. In the above case it would contain something like:

# Makefile
.PHONY: clean
 rm -f bundle*.js

make clean will now clean out all files created by the Makefile.


Directories in make usually needs a bit of special treatment. Let's say we want the bundles above to end up in a build directory. The following Makefile illustrates a problem.

# Makefile
bundles: build/bundle.js build/bundle2.js

build/bundle.js build/bundle2.js: jquery.js lib.js main.js
 cat $^ > $@

Running make illustrates the problem:

cat jquery.js lib.js main.js > build/bundle.js
/bin/sh: build/bundle.js: No such file or directory
make: *** [build/bundle.js] Error 1

The directory is not automatically created by cat. There are three ways to solve this and one is better than the others.

  1. Add mkdir -p to all rules creating files in the directory.
  2. Add a prerequisite to create the directory on the bundles target.
  3. Add an ordering prerequisite (|) to the rules creating the files in the directory.

1. is not good because the directory will be created more than once, one for each bundle (this is why the -p is needed). 2. is not good because the build directory is not a prerequisite target for bundles. 3. is good because the build directory is clearly a prerequisite of the rule that creates the bundles in this directory.

The reason we have to use an ordering prerequisite instead of a normal prerequisite is that cat would fail otherwise. Here's the resulting good Makefile.

# Makefile
bundles: build build/bundle.js build/bundle2.js

 mkdir build

build/bundle.js build/bundle2.js: jquery.js lib.js main.js | build
 cat $^ > $@

 rm -rf build


Now, we know the basics of Makefiles. We can create rules with targets, prerequisites and commands that are run when needed. But, we have been working with named files all this time. This works fine for small examples like above, but when we have hundreds of files this quickly gets out of hand. Patterns to the rescue.

Let's say that we have a bunch of images that we would like to optimize by running them through an optimizer. The images are in the images/ directory and the optimized images are built into build/images. The naive (and not working) way to do this is shown below. (I'm faking optimize with a simple copy, cp.) The % sign is glob matched with the part of the filename that is not literal.

# Makefile (NOT WORKING)
optimize: build/images/*

build/images/%: images/% | build/images
 cp $< $@

 mkdir -p $@

To see why this is not a viable Makefile, we try to run it with make.

$ make
mkdir -p build/images
cp images/a.png build/images/*.

$ tree build
└── images
    └── *

What is going on here? Why is only one image copied and why is it copied as name build/images/*? The problem is that the target files don't exist yet and the * is interpreted literally. If we copy the files into the build directory and touch the source files, it works the way we want.

# Copy the image directory into build
$ cp -r images build
# Touch the orignal images
$ touch images/*
# Build works since build/image/* evaluates to the list of images
$ make
cp images/a.png build/images/a.png
cp images/b.png build/images/b.png

Here is the main rule to know about patterns. The target file list has to be created from the available source files. To do this we have help of a number of functions, including wildcard, shell, etc. shell will allow us to call anything that we can call from the shell This is very powerful!

How do we solve the above problem? We can do this by getting a list of source images and transforming this list into a list of target images. This is easily done.

# Makefile

# 1. Get the souce list of images
images := $(wildcard images/*.png)

# 2. Tranform the source list into the target list
target_images := $(images:%=build/%)

# 3. Our default target, optimize, depends on all the target_images
optimize: $(target_images)

# 4. Build the targets from the sources, make sure build/images exist
$(target_images): build/% : % | build/images
 cp $< $@

 mkdir -p $@

The first line introduces both variables and functions.

Variables can be declared in a number of ways, but the :=-declaration is the simplest. It evaluates the value on the right and sets the value on the left to the result, like variables in most programming languages.

Functions are called with the $() construct, and wildcard is a function that evaluates a shell filename pattern and returns a list of filenames.

The full line above populates images with the .png files from the images directory.

The second line converts the source images into the target images. Variables are evaluated the same way as function calls, with the $() construct. By adding a colon-equals expression, a variable substitution reference, after the variable name we can substitute a pattern for another. Example

files := "src/ src/"
# Pattern replaces the files into "target/a.class target/b.class"
class_files := $(files:src/

The third line tells make that our optimize target depends on all the targets existing. This makes sure that all the targets are built.

The fourth line sets up the targets `$(target_images) and its prerequisites with a static pattern rule. The pattern does the opposite of the variable substitution reference above, it deconstructs a single target into the source it depends on. The final part of the of this line is an order prerequisite on the rule to create the directory.

A Recipe for Creating Makefiles

  • Create a list of targets that you want to create from the sources. You have the full power of bash, python, awk, etc. at your disposal.
  • Create a static pattern rule to convert a single target into the source it can be created from.
  • Add order prerequisites to make sure directories are automatically created.
  • Add a callable target that depends on all the target files that you want to create.

Commented Example

Here's a more exotic example of what you can use make for. We have a directory of Javascript source files in lib. The corresponding test files are in test. There may be multiple directories below both lib and test. The testfiles are named like the source files with an added .spec after the stem of the filename.

We want to use a makefile to help us run only the tests that are relevant based on the files that are changed. To keep track of what tests have been run we're going to use marker files and touch them every time a test is run.

# Create the list of test files by using the shell function and find
test_files := $(shell find test -name '*.spec.js' -print)

# Convert the test files into marker files with variable substitution
# A marker files looks like this tmp/model/person_test.marker
marker_files := $(test_files:%.js=tmp/%.marker)

# Do the same thing for the test directories
test_dirs := $(shell find test -type d -print)

# The marker directories have their normal names, no special ending
marker_dirs := $(test_dirs:%=tmp/%)

# test is the default target
.PHONY: test
test: $(marker_files)

# The marker files order depend on the marker directories
$(marker_files): | $(marker_dirs)

# Marker files depend on the source files
# Deconstruct a marker file into a source file
$(marker_files): tmp/test/%.spec.marker : lib/%.js

# Marker files depend on the test files
# Deconstruct the marker file into a test file
# When any prerequisite changes, run the tests and then touch the marker file
$(marker_files): tmp/%.marker : %.js
 mocha $<
 @touch $@

# Create the marker dirs
 @mkdir -p $@

# Clean the project by removing the entire tmp directory
.PHONY: clean
 rm -rf tmp

Now whenever you run make, it will run only the relevant tests.

# Modify a test file
$ touch test/models/passbook.spec.js
$ make
mocha test/models/passbook.spec.js
    ✓ generate pass strips image names
    ✓ doesnt crash with no store number
  2 passing (21ms)

# Modify a source file
$ touch lib/models/passbook.js
$ make
mocha test/models/passbook.spec.js
    ✓ generates pass strip image names
    ✓ doesnt crash with no store number
  2 passing (22ms)

Makefiles are really good at one thing: building only stale files. If that is our problem, we should give make a try.