HNHacker News
TopNewBestAskShowJobs

maktouch

245 karma · joined July 29, 2014

submissionscomments
maktouch··on Phabricator – GitHub Alternative written in PHP used by the Wikimedia Foundation
I love buildkite and I wish they had better pricing model -- we would definitely love to pay for more.

Pros of buildkite:

- Very powerful. Plugin system is amazing and easy to extend. We wrote our own buildkite-docker executor, and I merged a lot of parts from it to the docker plugin upstream

- UI is a lot prettier and responsive than Gitlab's

- Dynamic pipelines !

- Hooks are extensive and powerful. Precheckout, Checkout, PostCheckout, precommand, command, postcommand. You got it all.

- The GraphQL API is amazing, and probably one of the best API I've used in my life.

- Pipelines are composable. You can make a yaml include another yaml. This was our biggest gripe with Gitlab since we use a monorepo and it got pretty big

- I know for a lot of people it doesn't mean a lot, but I like emojis in the output

- Agents are not stored like Gitlab. In Gitlab, once an agent connects, it gets stored in the database and never disappear until you delete it. It's problematic for our use case, because we use pre-emptibles node to save cost. It's 30% of the real price, and it dies every 24 hours. after 3 months, our Gitlab got super slow because it retained all the infos on all runners that existed. I had to make a script that deleted it from the database.

- Job retries!

- Docs are pretty dope

- Annotate is very cool (https://buildkite.com/docs/agent/v3/cli-annotate)

- Block step. Useful for confirming before deploy or something.

- Pretty cheap (unlimited builds, you pay per user). Honestly, I would love to pay them more.

Cons of buildkite:

- It's not free, so Gitlab is hard to beat on that.

- Gitlab works fine for 99% of the use case.

Take a look at their changelog, a bunch of screenshots and you'll see their development pace =)

https://buildkite.com/changelog

maktouch··on Phabricator – GitHub Alternative written in PHP used by the Wikimedia Foundation
We run buildkite-agents in its own kubernetes cluster, and the nodes are pre-emptible on Google Cloud so 30% of the price and it dies everyday, so it gets cleanup automatically
maktouch··on Phabricator – GitHub Alternative written in PHP used by the Wikimedia Foundation
I don't find it as pretty as Phabricator's

"Merge branch 'dev-hello' into 'master'"

Phabricator makes it so that the squashed commit summary is the summary of the diff (merge request)

maktouch··on Phabricator – GitHub Alternative written in PHP used by the Wikimedia Foundation
We moved from Gitlab to Phab a year ago.

Context:

- One of the main repo is a monorepo in Git with over 40~ services

- We have a lot of smaller repos that are outdated or depreciated.

- We have an extensive pipeline that builds Docker images using Google Cloud Container Builder

Here's the pros:

- Speed. Gitlab is so slow; it's actually one of the main reasons why we moved out of it.

- Phabricator's Maniphest > Gitlab Issues by a long shot

- We prefer patch-based workflow. It makes Git history pretty.

- Code review is so much better in Phabricator, again, by a long shot. It's faster and the experience is a lot better.

- Herald (if-this-then-that for source code) is the bomb. We have a big list of rules, example: detecting `dangerouslySetInnerHTML` in our frontend service and adding blocking reviewers.

- Git management is pretty dope, setting it up so that it mirrors somewhere else is pretty easy. In our case, we just made it so that it mirrors to Google Cloud Repository (for GCCB to work)

- Cluster mode is included, which is useful because we're setting up a mirror Phab Repo in Russia for our team there - Meme editor makes things more fun (but its kinda shitty that it doesn't accept GIF =\) - The dashboard editor is very powerful and useful. - We had teams using SVN and teams using HG. Phab supports them all. That's pretty cool.

Here's the cons:

- Harbormaster, the CI, is the worst. It's seriously super complicated and not powerful at all.

- To replace Gitlab CI, we moved to Buildkite since there's an integration with Phab. Buildkite is a lot more powerful than Gitlab CI, and the syntax is similar.

- The concept of "staging" repo is super confusing.

- Setting up "merge" from the UI is very complicated and buggy

maktouch··on Re: Moving from PHP to Go and Back Again
Could you explain this? We use node everyday and I don't understand what you mean.
maktouch··on Introducing Conduit – open-source service mesh for Kubernetes
How does it work with ingress? Does it ship with its own ingress like istio?

We tried istio a while back and it was too slow and hungry. Reverted back to no service mesh and it worked fine. I'm gonna be trying this next!

maktouch··on Amazon EKS – Highly available and scalable Kubernetes service
Wow that's weird. We actually did the inverse, from AWS + Kops to GKE. In our case, the cluster just stopped working suddenly.

Been using GKE for over a year now. No issues at all.

maktouch··on Scaling the GitLab database
Right now:

- Self hosted Gitlab CE

- Gitlab runners in pre-emptibles nodes with autoscaling

Future (almost done, still in testing phase):

- Phabricator (for git, code review and issues)

- Jenkins ("lightweight" CI, more details at the bottom)

- Google Cloud Container Builder ("Heavyweight" CI)

Our main repository is in Phabricator, but it has mirroring to Google Cloud Repository (for backup and faster heavyweight builds)

On commits, we run the lightweight CI in Jenkins. What I mean by lightweight is that, there's only a few runners and what it does is check what has changed. We have a mono-repository with over 30 microservices, rebuilding all of them is a waste of time and resources, so we have scripts and easy to use manifests that defines what to do. We also have a lot of small CI checks that is just not worth it to run externally, like linting.

Here's what our homegrown manifests looks like

  build_graphql:
    when_changed:
      - graphql
      - node_libraries/player-graphdb
      - node_libraries/player-auth
      - node_libraries/player-models
    script_build: graphql/cloudbuild.yaml
    script_skip: graphql/cloudbuild-skip.yaml
The script skip takes the last successful build and retag the docker images to the current one. The build script sends the instructions to Google Cloud Container Builder to build the docker image, run the tests, and push it. We use Cloud Container Builder because managing those CI servers really sucks.

Let me know what else you want to know.

maktouch··on Scaling the GitLab database
We're moving away from gitlab because the performance is too much to bear. We're hearing "aaaaaarg I really hate gitlab" a few times a day.

The pipeline pages takes 7 seconds to load. It's really bad. We stopped using issues because just listing them was a chore. Pushing 1 file takes at least 30 seconds to 1 minute.

Anyways, the work falls on me to replace it. We're going with Phabricator and Jenkins.

maktouch··on Apollo Client 2.0
We're using Apollo v1 and tried the upgrade to v2 a few weeks ago. It was hard and buggy to replicate what we had (subscriptions, batched requests, polling requests). We reverted to v1 in the end because if the bugs and the complexity.

What really hurts us in v1 is the error handling. When querying a collection of items, if 1 item has an error, only the error is returned with no payload.

Hopefully all of these will get resolved the coming months.

maktouch··on Hacker News Clone Using GraphQL and React
The kind of query where it fails (and where it especially hurts) is queries like `getLatestNotifications`. It would be a lot of cruft added to prevent this kind of bugs.

So, yes, you know which one is bad, but it's not a query that's failing, it's something inside the result.

maktouch··on Hacker News Clone Using GraphQL and React
I really like the Apollo stack, but if you're thinking of using it in production right now, you should wait a little!

There's a massive bug where if your graphql outputs 1 small error, the whole component does not get loaded.

Imagine a components that lists a bunch of items. If 19 returned correctly but 1 has an error, the "data" prop doesn't get passed, all you receive back is the error prop. It's pretty shitty for that.

https://github.com/apollographql/react-apollo/issues/1112

Learned this the hard way :(

maktouch··on Why I’m dumping Firebase for Web
> Another problem GraphQL hasn't tackled (afaik) is polymorphism. You can say "hey give me this person" or "give me this company", but what if you want a customer that can be either a person or a company?

http://graphql.org/learn/schema/#interfaces

  searchPersonOrCompany(name: "abc") {
    ... on User {
     first_name
     last_name
    }
    ... on Company {
     business_name
    }
  }


As for the undetermined depths problem -- I agree to an extent.

GraphQL can't return depths without you querying for it unless one of the field is a JSON blob.. but at the same time, I like that it does that.

In your example of menu w/ submenus, I think I would prefer to load the first 2 level, then preload level 3 when level 2 is activated, and preload level 5 when level 4 is activated, and so on.

Apollo makes this quite easy.

maktouch··on You Might Not Need GraphQL
I agree that subscriptions are a work in progress, but how is mutations is a work in progress? Pretty sure it's defined and it works pretty well.
maktouch··on Gitlab 9.0
Ah! Finally found the culprit :-)

I run my fleet of runners in pre-emptible instances on GCP (they die after 24h).

I forgot to pin the version in my startup script, so all it did was a simple apt-get install gitlab-ci-multi-runner.

For some reason, version 9 of the gitlab runner cannot connect to our Gitlab (it fires a 404 on register).

Anyways, look like 9 is a cool release, but we won't be upgrading until the sidebar comes back (did a little poll in the team and it 100% was in favour of the sidebar)

maktouch··on Buck – A build system developed and used by Facebook
Pretty sure no one really doubted jQuery power.. it's about maintainability, state management, modularization.

If you tinker hard enough, you can achieve those with jQuery, but it'll never be as easy as React.

Also, your site doesn't load (project not found)

maktouch··on JSON Web Tokens should be avoided
That's weird. Cookies are part of the HTTP standard, no? That means iOS would be the one that is not respecting the RFC.

Kinda like Safari throwing exceptions when you're trying to access localstorage in incognito.

maktouch··on Converting a large React Codebase from Coffeescript to ES6
That's deprecated :(
maktouch··on Let’s Encrypt, OAuth 2, and Kubernetes Ingress
We started nginx-ingress as a deployment, and we converted it to a DaemonSet:

- We rarely deploy new versions of the ingress controller

- We can't (or don't know how to) choose in which nodes the pods will go. If I make a deployment with 10 replicas, there's a chance that it'll all go in the same node

- Because we can't choose to distribute the pods, when a node containing the ingress pod went down, there was a noticeable blip of downtime (~27 seconds approx.). That's kinda unacceptable.

- Nginx ingress is pretty light. I don't mind it having just 1 of them in each node.

- Since we put our databases and stateful stuff outside kubernetes, we also decided to separate web facing kubernetes cluster and worker ones. This solves the problem of the "spin up 50 new nodes to handle some batch machine learning job".

So far, so good. I would actually suggest that you use a DaemonSet for this, just like I suggest you convert Kube-DNS to a daemonset (it's not by default on GKE for some obscure reason).

maktouch··on Teaching Kubernetes
I found this last week and I'm very impressed because it solves a lot of the problems we had with existing ingresses.

I really like how you guys decided to do your own 3rd party manifests instead of using annotations.

I'm going to play more with this :-)

maktouch··on Teaching Kubernetes
I've been running K8S for the past 6 months. So far, so good. Helm helped us a lot in our workflow. A lot of trial and errors, but to answer your points, this is what we're doing so far:

> * Where do you store the YAML manifests, and how do you maintain them? Do you put them in the same git repo as your app, and if so, how do you deal with the fact that the YAML files are going to be different for production, staging, testing/QA, etc.? (For example, ingresses will use other host names. Configs are likely to be rather different altogether.)

We store the manifests in the same git repo as the app. Docker images and YAML files are all the same, what's different are the values, so we use helm and override the values per environment.

The values are split 4 ways: - default sensible values (values.yaml). For example, feature flags. - datacenter specific (gcp.yaml, aws.yaml). For example, REDIS_HOST and MYSQL_HOST. - environment values (env-production.yaml or env-staging.yaml). For example, the ingress values and its certs, how many replicas for each service - secrets.yaml (not stored in git, but generated on the fly, will explain more later). For example, MYSQL_PASSWORD

I mean, if you're doing your services right, they should all have the same docker images, only the config changes. Helm has a pretty good templating and config helpers.

> * Or if you centralize them in a single git repo, you have to make sure that you always pull the newest version, and that your workflow includes diffing against the currently deployed version, and so on.

Helm takes care of this. When you upgrade a deployment, it looks like it's doing a diff. What's cool though, is that it seems like it does a diff on everything except replicas, which is exactly what we needed.

> * How do you protect configs/secrets, if they're in git and available to all?

I don't mind having the config in git, I do when it comes to secret. We store secrets as a gitlab variable, and our CI dynamically creates a "secrets.yaml" before deploying. I'm still not really happy about this though, I think a better way would be to use Vault, but it adds some complexities that I'm not really to deal with yet.

> * Dependency tracking: If app A needs app B, you want to encapsulate that dependency in your workflow.

I'm not too sure I understand what you mean by this one. We, thankfully, merged all our git repos into 1 monolithic repository. I remember at first reading about the big boys (FB, MS, Google) having a single repository and thought they were crazy. Then we added more and more services and suddenly, I just realized that having a monorepo makes is a lot easier for developers and ops. AppA~1.0 needs AppB~2.5. We used to have a crazy graph of dependency like that. Not anymore. Now every services has the same version -- we're simply using git hashes. AppA~4c20d needs AppB-4c20d. Every push to the repo rebuilds the docker images and tags them like this: AppA:master-4c20d and AppB:master-4c20d. And yes, we build for all branches and all commits.

So for deploying, it's super easy. I just deploy everything at once, at all time. If I need to rollback, I can rollback to a specific version on all services. If I need to test in a real environment a specific version, all I do is add --set BRANCH=fix-bug-branch,COMMIT=4c20d

> * Continuous delivery: How do you take care of these concerns in relation to the CD system (e.g. Drone, Jenkins)?

There's no concerns here since every code push starts our pipeline, and the pipeline rebuilds all docker images, and runs the tests between each other. It's pretty dope.

> * And of course, you'll want to be able to develop locally. If you run Minikube, how do interact with it, YAML-wise?

We have a local bare-metal server running a single-node k8s, but to be honest, we've never had a dev needing to develop on K8S specifically. Each dev that builds a service is also tasked with building the dockerfile that goes with it, and with assistance, they build the YAML file that goes with it. It's pretty straightforward. Our gitlab auto deploys to dev, staging and review environment, so if there's an invalid YAML, the pipeline will catch it.

> There's Helm, but Helm is essentially just a "templates in a central repo" manager. It doesn't solve the configuration issue: You still need to provide values to the charts.

I think it does but not directly. It solves it because it allows you to use templates and override config in a sane way.

Here's an extract of our .gitlab-ci file for deploying to production

- echo "Deploying to Kubernetes Env=production Branch=$CI_BUILD_REF_NAME Version=$CI_BUILD_REF"

- "echo MYSQL_PASSWORD: $MYSQL_PASSWORD_PRODUCTION > tmp.yaml"

- "echo MYSQL_USERNAME: $MYSQL_USERNAME_PRODUCTION >> tmp.yaml"

- ... more secrets echo config here

- helm upgrade master ./manifests/App -f ./manifests/gcp.yaml -f ./manifests/env-production.yaml -f tmp.yaml --set BRANCH=master,COMMIT=$CI_BUILD_REF

> Right now I'm debating whether to just go for "simple and stupid" and have a central repo, and then build a small toolset to wrap kubectl for devs [...]

We started with building our own toolset to wrap kubectl. It worked. Then we found Helm. I remember at first looking at it and thought it wasn't useful for us.. now it looks pretty good. We heavily use templates to reduce boilerplate.

-----

I'm curious about your tool called Monkey. Is it a frontend for chef or ansible? Also, I can pretty much ask all the same questions you've asked but geared towards your tool (where do you store manifests, how do you protect config/secrets, how do do you handle dependency, continuous delivery, etc etc).

maktouch··on How Discord Stores Billions of Messages Using Cassandra
It's really interesting to see that you're using Cassandra for this. IIRC, Cassandra was created by Facebook for their messaging, and realized that eventual consistency was a bad model for chat, so they moved to HBase instead. (source: http://highscalability.com/blog/2010/11/16/facebooks-new-rea...)

The tombstone issue was really interesting ! Thanks for sharing.

maktouch··on GitLab 8.15 Released
I love gitlab! We just deployed our review app deployment to Kubernetes (create a new subdomain in route53, create a new namespace in k8s, create all kubernetes manifests in that namespace, create ingress manifest, boom!).

Here's some thing I wish for gitlab:

1. On merge, run "stop_review" so that we don't end up with a lot of old review apps.

2. I wish you could take over https://github.com/sameersbn/docker-gitlab or offer something similar. I find it a little crazy that you have a single docker image for redis, gitlab, postgresql. There's multiple reason why we don't want to use this, but the simplest is: we already have mysql running (and feel no need to move to pgsql), and we already have experience in running redis.. I kinda like my containers to do 1 thing and 1 thing well.

Merry Christmas, thanks for this patch!

maktouch··on Webpack 2.2 – Release Candidate
I think it really depends on what you work on.

> Almost a whole decade ago we had pretty simple and straight forward build patterns for frontend.

a decode ago, we didn't really build web apps like today though. The browser landscape was different. The technology was different.. but the most important: the expectation was different. Man, 10 years ago we still had flash.

> [...] help with productivity for some people but it just seems insanely overly complex to me

It is. To be honest, if I'd start today, I'd be super lost too.. but it is a one-time cost/investment to start to gain that productivity.

I think the biggest upside of this whole thing is working at scale in terms of human. Good modularization allows you to achieve this.. in the old school day, that was either a big javascript bundle, or a bunch of them inserted in the pages as global.

My opinion is: if you think you don't need it, don't bother with it. I didn't understand webpack until I needed it. I didn't understand React until I needed it. I didn't understand docker and kubernetes until I needed it. Trying to force yourself to use thing when you don't see the usefulness is counter productive.

maktouch··on Comparison with Other Frameworks
React can be used without JSX like Mithril is doing. In fact, pretty much all the JSX compiler does is convert those to React.createElement()..
← PreviousPage 2 of 2