One place for hosting & domains

      Create

      How To Create a Node.js Module


      The author selected the Open Internet/Free Speech Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      In Node.js, a module is a collection of JavaScript functions and objects that can be used by external applications. Describing a piece of code as a module refers less to what the code is and more to what it does—any Node.js file or collection of files can be considered a module if its functions and data are made usable to external programs.

      Because modules provide units of functionality that can be reused in many larger programs, they enable you to create loosely coupled applications that scale with complexity, and open the door for you to share your code with other developers. Being able to write modules that export useful functions and data will allow you to contribute to the wider Node.js community—in fact, all packages that you use on npm were bundled and shared as modules. This makes creating modules an essential skill for a Node.js developer.

      In this tutorial, you will create a Node.js module that suggests what color web developers should use in their designs. You will develop the module by storing the colors as an array, and providing a function to retrieve one randomly. Afterwards, you will run through various ways of importing a module into a Node.js application.

      Prerequisites

      Step 1 — Creating a Module

      This step will guide you through creating your first Node.js module. Your module will contain a collection of colors in an array and provide a function to get one at random. You will use the Node.js built-in exports property to make the function and array available to external programs.

      First, you’ll begin by deciding what data about colors you will store in your module. Every color will be an object that contains a name property that humans can easily identify, and a code property that is a string containing an HTML color code. HTML color codes are six-digit hexadecimal numbers that allow you to change the color of elements on a web page. You can learn more about HTML color codes by reading this HTML Color Codes and Names article.

      You will then decide what colors you want to support in your module. Your module will contain an array called allColors that will contain six colors. Your module will also include a function called getRandomColor() that will randomly select a color from your array and return it.

      In your terminal, make a new folder called colors and move into it:

      Initialize npm so other programs can import this module later in the tutorial:

      You used the -y flag to skip the usual prompts to customize your package.json. If this were a module you wished to publish to npm, you would answer all these prompts with relevant data, as explained in How To Use Node.js Modules with npm and package.json.

      In this case, your output will be:

      Output

      { "name": "colors", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }

      Now, open up a command-line text editor such as nano and create a new file to serve as the entry point for your module:

      Your module will do a few things. First, you’ll define a Color class. Your Color class will be instantiated with its name and HTML code. Add the following lines to create the class:

      ~/colors/index.js

      class Color {
        constructor(name, code) {
          this.name = name;
          this.code = code;
        }
      }
      

      Now that you have your data structure for Color, add some instances into your module. Write the following highlighted array to your file:

      ~/colors/index.js

      class Color {
        constructor(name, code) {
          this.name = name;
          this.code = code;
        }
      }
      
      const allColors = [
        new Color('brightred', '#E74C3C'),
        new Color('soothingpurple', '#9B59B6'),
        new Color('skyblue', '#5DADE2'),
        new Color('leafygreen', '#48C9B0'),
        new Color('sunkissedyellow', '#F4D03F'),
        new Color('groovygray', '#D7DBDD'),
      ];
      

      Finally, enter a function that randomly selects an item from the allColors array you just created:

      ~/colors/index.js

      class Color {
        constructor(name, code) {
          this.name = name;
          this.code = code;
        }
      }
      
      const allColors = [
        new Color('brightred', '#E74C3C'),
        new Color('soothingpurple', '#9B59B6'),
        new Color('skyblue', '#5DADE2'),
        new Color('leafygreen', '#48C9B0'),
        new Color('sunkissedyellow', '#F4D03F'),
        new Color('groovygray', '#D7DBDD'),
      ];
      
      exports.getRandomColor = () => {
        return allColors[Math.floor(Math.random() * allColors.length)];
      }
      
      exports.allColors = allColors;
      

      The exports keyword references a global object available in every Node.js module. All functions and objects stored in a module’s exports object are exposed when other Node.js modules import it. The getRandomColor() function was created directly on the exports object, for example. You then added an allColors property to the exports object that references the local constant allColors array created earlier in the script.

      When other modules import this module, both allColors and getRandomColor() will be exposed and available for usage.

      Save and exit the file.

      So far, you have created a module that contains an array of colors and a function that returns one randomly. You have also exported the array and function, so that external programs can use them. In the next step, you will use your module in other applications to demonstrate the effects of export.

      Step 2 — Testing your Module with the REPL

      Before you build a complete application, take a moment to confirm that your module is working. In this step, you will use the REPL to load the colors module. While in the REPL, you will call the getRandomColor() function to see if it behaves as you expect it to.

      Start the Node.js REPL in the same folder as the index.js file:

      When the REPL has started, you will see the > prompt. This means you can enter JavaScript code that will be immediately evaluated. If you would like to read more about this, follow our guide on using the REPL.

      First, enter the following:

      • colors = require('./index');

      In this command, require() loads the colors module at its entry point. When you press ENTER you will get:

      Output

      { getRandomColor: [Function], allColors: [ Color { name: 'brightred', code: '#E74C3C' }, Color { name: 'soothingpurple', code: '#9B59B6' }, Color { name: 'skyblue', code: '#5DADE2' }, Color { name: 'leafygreen', code: '#48C9B0' }, Color { name: 'sunkissedyellow', code: '#F4D03F' }, Color { name: 'groovygray', code: '#D7DBDD' } ] }

      The REPL shows us the value of colors, which are all the functions and objects imported from the index.js file. When you use the require keyword, Node.js returns all the contents within the exports object of a module.

      Recall that you added getRandomColor() and allColors to exports in the colors module. For that reason, you see them both in the REPL when they are imported.

      At the prompt, test the getRandomColor() function:

      You’ll be prompted with a random color:

      Output

      Color { name: 'groovygray', code: '#D7DBDD' }

      As the index is random, your output may vary. Now that you confirmed that the colors module is working, exit the Node.js REPL:

      This will return you to your terminal command line.

      You have just confirmed that your module works as expected using the REPL. Next, you will apply these same concepts and load your module into an application, as you would do in a real project.

      Step 3 — Saving your Local Module as a Dependency

      While testing your module in the REPL, you imported it with a relative path. This means you used the location of the index.js file in relation to the working directory to get its contents. While this works, it is usually a better programming experience to import modules by their names so that the import is not broken when the context is changed. In this step, you will install the colors module with npm’s local module install feature.

      Set up a new Node.js module outside the colors folder. First, go to the previous directory and create a new folder:

      • cd ..
      • mkdir really-large-application

      Now move into your new project:

      • cd really-large-application

      Like with the colors module, initialize your folder with npm:

      The following package.json will be generated:

      Output

      { "name": "really-large-application", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }

      Now, install your colors module and use the --save flag so it will be recorded in your package.json file:

      • npm install --save ../colors

      You just installed your colors module in the new project. Open the package.json file to see the new local dependency:

      You will find that the following highlighted lines have been added:

      ~/really-large-application/package.json

      {
        "name": "really-large-application",
        "version": "1.0.0",
        "description": "",
        "main": "index.js",
        "scripts": {
          "test": "echo "Error: no test specified" && exit 1"
        },
        "keywords": [],
        "author": "",
        "license": "ISC",
        "dependencies": {
          "colors": "file:../colors"
        }
      }
      

      Exit the file.

      The colors module was copied to your node_modules directory. Verify it’s there with the following command:

      This will give the following output:

      Output

      colors

      Use your installed local module in this new program. Re-open your text editor and create another JavaScript file:

      Your program will first import the colors module. It will then choose a color at random using the getRandomColor() function provided by the module. Finally, it will print a message to the console that tells the user what color to use.

      Enter the following code in index.js:

      ~/really-large-application/index.js

      const colors = require('colors');
      
      const chosenColor = colors.getRandomColor();
      console.log(`You should use ${chosenColor.name} on your website. It's HTML code is ${chosenColor.code}`);
      

      Save and exit this file.

      Your application will now tell the user a random color option for a website component.

      Run this script with:

      Your output will be similar to:

      Output

      You should use leafygreen on your website. It's HTML code is #48C9B0

      You’ve now successfully installed the colors module and can manage it like any other npm package used in your project. However, if you added more colors and functions to your local colors module, you would have to run npm update in your applications to be able to use the new options. In the next step, you will use the local module colors in another way and get automatic updates when the module code changes.

      Step 4 — Linking a Local Module

      If your local module is in heavy development, continually updating packages can be tedious. An alternative would be to link the modules. Linking a module ensures that any updates to the module are immediately reflected in the applications using it.

      In this step, you will link the colors module to your application. You will also modify the colors module and confirm that its most recent changes work in the application without having to reinstall or upgrade.

      First, uninstall your local module:

      npm links modules by using symbolic links (or symlinks), which are references that point to files or directories in your computer. Linking a module is done in two steps:

      1. Creating a global link to the module. npm creates a symlink between your global node_modules directory and the directory of your module. The global node_modules directory is the location in which all your system-wide npm packages are installed (any package you install with the -g flag).
      2. Create a local link. npm creates a symlink between your local project that’s using the module and the global link of the module.

      First, create the global link by returning to the colors folder and using the link command:

      • cd ../colors
      • sudo npm link

      Once complete, your shell will output:

      Output

      /usr/local/lib/node_modules/colors -> /home/sammy/colors

      You just created a symlink in your node_modules folder to your colors directory.

      Return to the really-large-application folder and link the package:

      • cd ../really-large-application
      • sudo npm link colors

      You will receive output similar to the following:

      Output

      /home/sammy/really-large-application/node_modules/colors -> /usr/local/lib/node_modules/colors -> /home/sammy/colors

      Note: If you would like to type a bit less, you can use ln instead of link. For example, npm ln colors would have worked the exact same way.

      As the output shows, you just created a symlink from your really-large-application’s local node_modules directory to the colors symlink in your global node_modules, which points to the actual directory with the colors module.

      The linking process is complete. Run your file to ensure it still works:

      Your output will be similar to:

      Output

      You should use sunkissedyellow on your website. It's HTML code is #F4D03F

      Your program functionality is intact. Next, test that updates are immediately applied. In your text editor, re-open the index.js file in the colors module:

      • cd ../colors
      • nano index.js

      Now add a function that selects the very best shade of blue that exists. It takes no arguments, and always returns the third item of the allColors array. Add these lines to the end of the file:

      ~/colors/index.js

      class Color {
        constructor(name, code) {
          this.name = name;
          this.code = code;
        }
      }
      
      const allColors = [
        new Color('brightred', '#E74C3C'),
        new Color('soothingpurple', '#9B59B6'),
        new Color('skyblue', '#5DADE2'),
        new Color('leafygreen', '#48C9B0'),
        new Color('sunkissedyellow', '#F4D03F'),
        new Color('groovygray', '#D7DBDD'),
      ];
      
      exports.getRandomColor = () => {
              return allColors[Math.floor(Math.random() * allColors.length)];
              }
      
      exports.allColors = allColors;
      
      exports.getBlue = () => {
        return allColors[2];
      }
      

      Save and exit the file, then re-open the index.js file in the really-large-application folder:

      • cd ../really-large-application
      • nano index.js

      Make a call to the newly created getBlue() function, and print a sentence with the color’s properties. Add these statements to the end of the file:

      ~/really-large-application/index.js

      const colors = require('colors');
      
      const chosenColor = colors.getRandomColor();
      console.log(`You should use ${chosenColor.name} on your website. It's HTML code is ${chosenColor.code}`);
      
      const favoriteColor = colors.getBlue();
      console.log(`My favorite color is ${favoriteColor.name}/${favoriteColor.code}, btw`);
      

      Save and exit the file.

      The code now uses the newly create getBlue() function. Execute the file as before:

      You will get output like:

      Output

      You should use brightred on your website. It's HTML code is #E74C3C My favorite color is skyblue/#5DADE2, btw

      Your script was able to use the latest function in your colors module, without having to run npm update. This will make it easier to make changes to this application in development.

      As you write larger and more complex applications, think about how related code can be grouped into modules, and how you want these modules to be set up. If your module is only going to be used by one program, it can stay within the same project and be referenced by a relative path. If your module will later be shared separately or exists in a very different location from the project you are working on now, installing or linking might be more viable. Modules in active development also benefit from the automatic updates of linking. If the module is not under active development, using npm install may be the easier option.

      Conclusion

      In this tutorial, you learned that a Node.js module is a JavaScript file with functions and objects that can be used by other programs. You then created a module and attached your functions and objects to the global exports object to make them available to external programs. Finally, you imported that module into a program, demonstrating how modules come together into larger applications.

      Now that you know how to create modules, think about the type of program you want to write and break it down into various components, keeping each unique set of activities and data in their own modules. The more practice you get writing modules, the better your ability to write quality Node.js programs on your learning journey. To work through an example of a Node.js application that uses modules, see our How To Set Up a Node.js Application for Production on Ubuntu 18.04 tutorial.



      Source link

      How to Create a Website for Your Event (In 4 Steps)


      Planning events can be both fun and strenuous. Whether you’re working on the fundraiser of the year, a huge wedding, or an academic conference, you might be wondering how you can create an appealing online presence for the upcoming event.

      Fortunately, creating an event website using WordPress can be fast and easy. As an open-source Content Management System (CMS), WordPress has a ton of built-in flexibility. Additionally, the platform has a vast community of helpful users and developers that you can reach out to for help.

      In this article, we’re going to discuss why WordPress is a smart choice for your event website. Then we’ll walk you through all the steps needed to create your own event website using WordPress. Let’s jump right in!

      Why You Should Consider a WordPress Site for Your Event

      There are many reasons WordPress is an excellent platform for building an event website. For example, it offers both ease of editing and a high level of flexibility. Plus, the platform is always free to download.

      What’s more, since WordPress is built using open-source code, developers all over the world have added onto the platform’s core functionality with plugins. This means there are many options for enhancing your site with event-specific, niche plugins that can help you easily track, promote, and share your event in order to boost registrations.

      Another benefit to building with this CMS is that it doesn’t matter how big or how small your event might be — WordPress always fits like a glove! Fortunately, building your event website using WordPress doesn’t have to be difficult at all.

      WordPress + DreamHost

      Our automatic updates and strong security defenses take server management off your hands so you can focus on building a great event website.

      How to Create a WordPress Site for Your Event (In 4 Steps)

      To get started with your WordPress event site, all you need to do is follow these four steps. Each will help you get up and running as quickly as possible, so you can move on to planning and hosting the event itself.

      1. Choose a Secure and Professional Hosting Platform

      While the WordPress software is free, you’ll still need to host your site somewhere. Choosing a web host can seem overwhelming at first, but it’s an essential first step in getting your event site started.

      A web host is where all of your site’s data is stored, along with the files that create the functionality you’ll need to manage your event. There are a few things to consider when choosing your host since there are lots of options out there.

      You’ll want to make sure the host you choose has the support you might need for certain types of events. You may need to accommodate a live stream, for example, or your event might require higher bandwidth for heavy registration traffic.

      Here at DreamHost, we have several Virtual Private Server (VPS) options that can suit a wide variety of event planning needs.

      DreamHost VPS pricing.

      We recommend really getting a feel for all the different types of hosting out there. That way, you can make sure your event website is stored in the most secure, high-performance location possible.

      2. Select a Theme to Suit Your Event

      Once you’ve installed WordPress on your hosting plan, you can move on to some of the more exciting parts of building a website!

      Choosing a theme can be a lot of fun, and it’s also a vital step. That’s especially true if you are looking to create a cohesive brand or send out a certain “vibe” about your event.

      There are two main ways you can obtain WordPress themes, including:

      • Downloading free themes from the WordPress Theme Directory
      • Purchasing premium themes from a theme marketplace or directly from a developer

      Themes often come with built-in functionality or features that you’ll want to understand before installing them. If you know you need a certain kind of layout, footer, or sidebar, for example, you’ll want to make sure the theme you pick can handle that type of design.

      Some of the free themes available in the directory are nearly as packed with features as premium themes that come with a price tag. Reading their reviews and checking to see when each theme was last updated are smart ways to decide which is best for your site.

      Of course, it’s also important to remember that sometimes niche themes can be more helpful than general, all-purpose themes. For example, ShowThemes offers event-specific WordPress themes and lets you search its database by feature set so you can find exactly what you’re looking for.

      The ShowThemes home page.

      ShowThemes covers the full spectrum of possible events you might want to promote. For instance, if you just need a one-page site for a conference, the Fudge theme is a solid option. Not only is it already optimized for mobile devices, but it also has a clear and easy-to-customize design for your Call-to-Action.

      The Fudge theme.

      Starting with a theme designed for the type of event you’re promoting can save you a lot of time, so it’s well worth considering.

      3. Add Event and E-Commerce Plugins to Manage Registration

      There are a few more universal aspects of event planning to keep in mind while building your WordPress event site. Typically, events require some kind of registration process, guest list, or check-in management (just to name a few examples).

      Whether or not your event is free-of-charge or requires payment, adding event and e-commerce plugins to your site can be extremely helpful. There are a number of ways to build in the functionality you’ll need to handle ticket sales or registrations.

      Event Espresso, for instance, is an all-in-one plugin solution that covers everything from setting up a registration form to using payment gateways.

      The Event Espresso plugin.

      While the free version provides plenty of functionality, you can purchase Event Espresso’s premium tier if you’re interested in add-on features such as printable tickets, ticket scanning, and waitlists.

      If you need a plugin that specializes in managing a guest list and registration data, on the other hand, you might want to check out the RSVP and Event Management plugin.

      The RSVP and Event Management plugin.

      Additionally, you can maximize WordPress’ flexibility by using plugins that make it possible to connect to outside event software, such as EventBrite, to help you manage your event. While this method requires you to have an account with the platform, it’s still an excellent option if you have specific event management applications you know and love.

      4. Promote Your Event on Social Media

      Once you’ve built your event site, you’ll likely want to start getting the word out and encouraging registrations. It’s no secret that social media is probably the best way to share your event with your target audience, as widely or as privately as you want.

      One of the most straightforward ways to promote your event on social media is to let your website visitors do it for you, through adding social sharing buttons to your website. You can add on a plugin like Sassy Social Share, for example, and choose from over 100 social media and bookmarking site buttons to add to your site.

      The Sassy Social Share plugin.

      If you want to take things a step further, and proactively push your event content and site updates to a variety of social media sites, you can check out the free plugin Blog2Social. This tool gives you the option to set up automatic posts from your website to 14 different social networks.

      The Blog2Social plugin.

      With Blog2Social, you can also cross-post content, schedule updates, and automatically post new content. Additionally, you can customize your posts with comments and hashtags, for even more engagement and appeal.

      You can even enable guests to register for your event via their existing social media accounts. Adding the Social Login plugin to your event site makes that simple.

      The Social Login plugin.

      Whether you’re looking to push content to social media accounts, or pull in guests and registrations via social channels, adding some of these helpful plugins to your event site can help you stand out from the pack and attract attention.

      Easy Event Marketing

      If you’ve been worried about how to get your event website off the ground, while also planning for all your other event-related needs, we hope this step-by-step guide has helped to ease your burden a bit. WordPress can help you get your site up and running quickly, which leaves you plenty of time to focus on all the other details that make for a great event.

      Here at DreamHost, WordPress is always invited to the party. Check out our WordPress hosting plans and get your event website online today!



      Source link

      How To Create an API Gateway Using Ambassador on DigitalOcean Kubernetes


      The author selected the Free and Open Source Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Ambassador is an API Gateway for cloud-native applications that routes traffic between heterogeneous services and maintains decentralized workflows. It acts as a single entry point and supports tasks like service discovery, configuration management, routing rules, and rate limiting. It provides great flexibility and ease of configuration for your services.

      Envoy is an open source service proxy designed for cloud-native applications. In Kubernetes, Ambassador can be used to install and manage Envoy configuration. Ambassador supports zero downtime configuration changes and integration with other features like authentication, service discovery, and services meshes.

      In this tutorial, you’ll set up an Ambassador API Gateway on a Kubernetes cluster using Helm and configure it for routing incoming traffic to various services based on routing rules. You’ll configure these rules to route the traffic based on hostname or path to the relevant services.

      Prerequisites

      Before you begin this guide you’ll need the following:

      Step 1 — Installing Ambassador

      In this section, you will install Ambassador on your Kubernetes cluster. Ambassador can be installed using a Helm chart or by passing a YAML configuration file to the kubectl command.

      Note: DigitalOcean Kubernetes has RBAC enabled by default, so when using a YAML configuration file for installation you need to ensure that you use the RBAC enabled one. You can find further details about deploying Amabassador to Kubernetes via YAML in Ambassador’s documentation.

      For the purposes of this tutorial, you’ll use a Helm chart to install Ambassador to your cluster. Having followed the prerequisites, you’ll have Helm installed to your cluster.

      To begin, run the following command to install Ambassador via Helm:

      • helm upgrade --install --wait ambassador stable/ambassador

      You’ll see output similar to the following:

      Output

      Release "ambassador" does not exist. Installing it now. NAME: ambassador LAST DEPLOYED: Tue Jun 18 02:15:00 2019 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Deployment NAME READY UP-TO-DATE AVAILABLE AGE ambassador 3/3 3 3 2m39s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE ambassador-7d55c468cb-4gpq9 1/1 Running 0 2m38s ambassador-7d55c468cb-jr9zr 1/1 Running 0 2m38s ambassador-7d55c468cb-zhm7l 1/1 Running 0 2m38s ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ambassador LoadBalancer 10.245.183.114 139.59.52.164 80:30001/TCP,443:31557/TCP 2m40s ambassador-admins ClusterIP 10.245.46.43 <none> 8877/TCP 2m41s ==> v1/ServiceAccount NAME SECRETS AGE ambassador 1 2m43s ==> v1beta1/ClusterRole NAME AGE ambassador 2m41s ==> v1beta1/ClusterRoleBinding NAME AGE ambassador 2m41s ==> v1beta1/CustomResourceDefinition NAME AGE authservices.getambassador.io 2m42s consulresolvers.getambassador.io 2m41s kubernetesendpointresolvers.getambassador.io 2m42s kubernetesserviceresolvers.getambassador.io 2m43s mappings.getambassador.io 2m41s modules.getambassador.io 2m41s ratelimitservices.getambassador.io 2m42s tcpmappings.getambassador.io 2m41s tlscontexts.getambassador.io 2m42s tracingservices.getambassador.io 2m43s . . .

      This will create an Ambassador deployment, service, and a Load Balancer with your Kubernetes cluster nodes attached. You’ll need the Load Balancer’s IP to map it to your domain’s A records.

      To get the IP address of your Ambassador Load Balancer, run the following:

      • kubectl get svc --namespace default ambassador

      You’ll see output similar to:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ambassador LoadBalancer your_cluster_IP your-IP-address 80:30001/TCP,443:31557/TCP 8m4s

      Note the external IP your-IP-address in this step and map the domains (via your domain provider) svc1.your-domain, svc2.your-domain, and svc3.your-domain to point to this IP address.

      You can enable HTTPS with your DigitalOcean Load Balancer using the steps given at How to Configure SSL Termination. It is recommended to configure TLS termination via the Load Balancer. Another way of configuring TLS termination is using Ambassador’s TLS Support

      You’ve installed Ambassador on your Kubernetes cluster using Helm which created an Ambassador deployment with three replicas in the default namespace. This also created a Load Balancer with a public IP to route all traffic toward the API Gateway. Next you’ll create Kubernetes deployments for three different services that you’ll be using to test this API Gateway.

      Step 2 — Setting Up Web Server Deployments

      In this section, you’ll create three deployments to run three different web server containers. You’ll create YAML files with definitions of Kubernetes deployments for the three different web server containers and deploy them using kubectl.

      Open your preferred text editor to create your first deployment for an Nginx web server:

      Enter the following yaml configuration in your file:

      svc1-deploy.yaml

      apiVersion: extensions/v1beta1
      kind: Deployment
      metadata:
        name: svc1
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: nginx
            name: svc1
        strategy:
          type: RollingUpdate
        template:
          metadata:
            labels:
              app: nginx
              name: svc1
          spec:
            containers:
            - name: nginx
              image: nginx:latest
              ports:
              - name: http
                containerPort: 80
      

      Here you have defined a Kubernetes Deployment with the nginx:latest container image to be deployed with 1 replica, called svc1. The Deployment is defined to expose in-cluster at port 80.

      Save and close the file.

      Then run the following command to apply this configuration:

      • kubectl apply -f svc1-deploy.yaml

      You’ll see output confirming creation:

      Output

      deployment.extensions/svc1 created

      Now, create a second web server deployment. Open a file called svc2-deploy.yaml with:

      Enter the following YAML configuration in the file:

      svc2-deploy.yaml

      apiVersion: extensions/v1beta1
      kind: Deployment
      metadata:
        name: svc2
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: httpd
            name: svc2
        strategy:
          type: RollingUpdate
        template:
          metadata:
            labels:
              app: httpd
              name: svc2
          spec:
            containers:
            - name: httpd
              image: httpd:latest
              ports:
              - name: http
                containerPort: 80
      

      Here you have defined a Kubernetes Deployment with the httpd container image to be deployed with 1 replica, called svc2.

      Save and close the file.

      Run the following command to apply this configuration:

      • kubectl apply -f svc2-deploy.yaml

      You’ll see this output:

      Output

      deployment.extensions/svc2 created

      Finally for the third deployment, open and create the svc3-deploy.yaml file:

      Add the following lines to the file:

      svc3-deploy.yaml

      apiVersion: extensions/v1beta1
      kind: Deployment
      metadata:
        name: svc3
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: httpbin
            name: svc3
        strategy:
          type: RollingUpdate
        template:
          metadata:
            labels:
              app: httpbin
              name: svc3
          spec:
            containers:
            - name: httpbin
              image: kennethreitz/httpbin:latest
              ports:
              - name: http
                containerPort: 80
      

      Here you have defined a Kubernetes Deployment with the httpbin container image to be deployed with 1 replica, called svc3.

      Save and close the file.

      Finally, run the following command to apply:

      • kubectl apply -f svc3-deploy.yaml

      And you’ll see the following output:

      Output

      deployment.extensions/svc3 created

      You’ve deployed three web server containers using Kubernetes deployments. In the next step, you will be exposing these deployments to internet traffic.

      Step 3 — Exposing Apps Using Services with Ambassador Annotations

      In this section, you will expose your web apps to the internet creating Kubernetes Services with Ambassador annotations to configure rules to route traffic to them. Annotations in Kubernetes are a way to add metadata to objects. Ambassador uses these annotation values from services to configure its routing rules.

      As a reminder you need to have your domains (for example: svc1.your-domain, svc2.your-domain, and svc3.your-domain) mapped to the Load Balancer’s public IP in your DNS records.

      Define a Kubernetes service for the svc1 deployment with Ambassador annotations by creating and opening this file:

      Note: The mapping name should be unique for every Ambassador annotation block. The mapping acts as an identifier for every annotation block and if repeated it will overlap the older annotation block.

      svc1-service.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: svc1
        annotations:
          getambassador.io/config: |
            ---
            apiVersion: ambassador/v1
            kind: Mapping
            name: svc1-service_mapping
            host: svc1.your-domain
            prefix: /
            service: svc1:80
      spec:
        selector:
          app: nginx
          name: svc1
        ports:
        - name: http
          protocol: TCP
          port: 80
      

      In this YAML code, you have defined a Kubernetes service svc1 with Ambassador annotations to map hostname svc1.your-domain to this service.

      Save and exit svc1-service.yaml, and then execute the following to apply this configuration:

      • kubectl apply -f svc1-service.yaml

      You’ll see this output:

      Output

      service/svc1 created

      Create your second Kubernetes service for svc2 deployment with Ambassador annotations. This is another example of host-based routing with Ambassador:

      Add the following configuration to the file:

      svc2-service.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: svc2
        annotations:
          getambassador.io/config: |
            ---
            apiVersion: ambassador/v1
            kind: Mapping
            name: svc2-service_mapping
            host: svc2.your-domain
            prefix: /
            service: svc2:80
      spec:
        selector:
          app: httpd
          name: svc2
        ports:
        - name: http
          protocol: TCP
          port: 80
      

      Save this as svc2-service.yaml. Here, you’ve defined another Kubernetes service with Ambassador annotations to route traffic to svc2 when any request is received by Ambassador with the host header value as svc2.your-domain. Therefore this host-based routing will allow you to send a request to the subdomain svc2.your-domain, which will route the traffic to the service svc2 and serve your request from httpd web server.

      To create this service, execute the following:

      • kubectl apply -f svc2-service.yaml

      You’ll see the following output:

      Output

      service/svc2 created

      Create a third Kubernetes service for your svc3 deployment and serve it via the path svc2.your-domain/bin. This will configure path-based routing for Ambassador:

      svc3-service.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: svc3
      spec:
        selector:
          app: httpbin
          name: svc3
        ports:
        - name: http
          protocol: TCP
          port: 80
      

      Save this as svc3-service.yaml and run the following to apply the configuration:

      • kubectl apply -f svc3-service.yaml

      Your output will be:

      Output

      service/svc3 created

      Edit svc2-service.yaml to append the second Ambassador annotation block to route /bin to svc3 service:

      svc2-service.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: svc2
        annotations:
          getambassador.io/config: |
            ---
            apiVersion: ambassador/v1
            kind: Mapping
            name: svc2-service_mapping
            host: svc2.your-domain
            prefix: /
            service: svc2:80
            ---
            apiVersion: ambassador/v1
            kind: Mapping
            name: svc3-service_mapping
            host: svc2.your-domain
            prefix: /bin
            service: svc3:80
      spec:
        selector:
          app: httpd
          name: svc2
        ports:
        - name: http
          protocol: TCP
          port: 80
      

      You’ve added the second Ambassador annotation block to configure paths beginning with /bin to map to your svc3 Kubernetes service. In order to route requests for svc2.your-domain/bin to svc3, you have added the second annotation block here as the host value svc2.your-domain, which is the same for both of the blocks. Therefore path-based routing will allow you to send a request to svc2.your-domain/bin, which will be received by service svc3 and served by the httpbin application in this tutorial

      Now run the following to apply the changes:

      • kubectl apply -f svc2-service.yaml

      You’ll see this output:

      Output

      service/svc2 configured

      You have created Kubernetes Services for the three deployments and added host-based and path-based routing rules with Ambassador annotations. Next, you’ll add advanced configuration to these services to configure routing, redirection, and custom headers.

      Step 4 — Advanced Ambassador Configurations for Routing

      In this section, you will configure the services with further Ambassador annotations to modify headers and configure redirection.

      curl the domain svc1.your-domain and check the response headers:

      Your output will be similar to the following:

      Output

      HTTP/1.1 200 OK server: envoy date: Mon, 17 Jun 2019 21:41:00 GMT content-type: text/html content-length: 612 last-modified: Tue, 21 May 2019 14:23:57 GMT etag: "5ce409fd-264" accept-ranges: bytes x-envoy-upstream-service-time: 0

      This output shows the headers received from the service routed using Ambassador. You’ll add custom headers to your service response using Ambassador annotations and validate the output for new added headers.

      To add custom headers to your service response, remove the header x-envoy-upstream-service-time from the response and add a new response header x-geo-location: India for svc1. (You may change this header as per your requirements.)

      Edit the file svc1-service.yaml:

      Update the annotation with the following highlighted lines:

      svc1-service.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: svc1
        annotations:
          getambassador.io/config: |
            ---
            apiVersion: ambassador/v1
            kind: Mapping
            name: svc1-service_mapping
            host: svc1.example.com
            prefix: /
            remove_response_headers:
            - x-envoy-upstream-service-time
            add_response_headers:
              x-geo-location: India
            service: svc1:80
      spec:
        selector:
          app: nginx
          name: svc1
        ports:
        - name: http
          protocol: TCP
          port: 80
      

      Here you have modified the svc1 service to remove x-envoy-upstream-service-time and added the x-geo-location: India header in the HTTP response.

      Apply the changes you have made:

      • kubectl apply -f svc1-service.yaml

      You will see the following output:

      Output

      service/svc1 configured

      Now run curl to validate the updated headers in the service response:

      The output will be similar to this:

      Output

      HTTP/1.1 200 OK server: envoy date: Mon, 17 Jun 2019 21:45:26 GMT content-type: text/html content-length: 612 last-modified: Tue, 21 May 2019 14:23:57 GMT etag: "5ce409fd-264" accept-ranges: bytes x-geo-location: India

      Now edit svc3-service.yaml to redirect requests for your hostname svc3.your-domain to path svc2.your-domain/bin:

      Append the Ambassador annotation block as shown in the following YAML and save it:

      svc3-service.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: svc3
        annotations:
          getambassador.io/config: |
            ---
            apiVersion: ambassador/v1
            kind:  Mapping
            name:  redirect_mapping
            host: svc3.your-domain
            prefix: /
            service: svc2.your-domain
            host_redirect: true
            path_redirect: /bin
      spec:
        selector:
          app: httpbin
          name: svc3
        ports:
        - name: http
          protocol: TCP
          port: 80
      

      You’ve added host_redirect: true to configure a 301 redirection response for svc3 to svc2.your-domain/bin for hostname svc3.your-domain. The host_redirect parameter sends a 301 redirection response to the client. If not set, the requests will receive 200 HTTP responses rather than 301 HTTP responses.

      Now run the following command to apply these changes:

      • kubectl apply -f svc3-service.yaml

      You will see similar output to:

      Output

      service/svc3 configured

      You can now check the response for svc3.your-domain using curl:

      Your output will be similar to the following:

      Output

      HTTP/1.1 301 Moved Permanently location: http://svc2.your-domain/bin date: Mon, 17 Jun 2019 21:52:05 GMT server: envoy transfer-encoding: chunked

      The output is a HTTP header for the request’s response to the service svc3.your-domainshowing that the configuration of host_redirect: true in your service annotation has correctly provided the HTTP status code: 301 Moved Permanently.

      You’ve configured the service with Ambassador annotations to modify HTTP headers and configure redirections. Next you will be adding global configuration to the Ambassador API Gateway service.

      Step 5 — Setting Up Ambassador Global Configurations

      In this section, you will edit the Ambassador service to add global GZIP compression configuration. GZIP compression will compress the HTTP assets size and reduce network bandwidth requirements leading to faster response times for the web clients. This configuration affects all the traffic being routed out through the Ambassador API Gateway. Similarly, you can configure other global modules with Ambassador, which let you enable special behaviors for Ambassador at a global level. These global configurations can be applied using annotations to the Ambassador service. You can refer to Ambassador’s Global Configuration documentation for further information.

      The following kubectl edit command will open the default editor, which is vim. To use nano, for example, you can set the environment variable KUBE_EDITOR to nano:

      • export KUBE_EDITOR="nano"

      Edit the Ambassador service:

      • kubectl edit service ambassador

      Now add the highlighted lines to a new annotation block for GZIP compression:

      Editing Ambassador Service

      apiVersion: v1
      kind: Service
      metadata:
        annotations:
          getambassador.io/config: |
            ---
            apiVersion: ambassador/v1
            kind: Module
            name: ambassador
            config:
              service_port: 8080
            ---
            apiVersion: ambassador/v0
            kind:  Module
            name:  ambassador
            config:
              gzip:
                memory_level: 5
                min_content_length: 256
                compression_level: BEST
                compression_strategy: DEFAULT
                content_type:
                - application/javascript
                - application/json
                - text/html
                - text/plain
                disable_on_etag_header: false
                remove_accept_encoding_header: false
        creationTimestamp: "2019-06-17T20:45:04Z"
        labels:
          app.kubernetes.io/instance: ambassador
          app.kubernetes.io/managed-by: Tiller
          app.kubernetes.io/name: ambassador
          helm.sh/chart: ambassador-2.8.2
        name: ambassador
        namespace: default
        resourceVersion: "2153"
        . . .
      

      You’ve added the Ambassador annotation block to your Ambassador service and configured GZIP globally for the API Gateway. Here you have included configuration to control the amount of internal memory used with memory_level, which can be a value from 1 to 9. The compression_level set at BEST ensures a higher compression rate at the cost of higher latency. With min_content_length you have configured the minimum response length to 256 bytes. For content_type you’ve specifically included a set of media types (formerly MIME-types) that yield compression. Finally you added the final two configurations as false to allow for compression.

      You can read more about GZIP compression on Envoy’s GZIP page.

      Any changes in this service apply as global configurations for the API Gateway.

      Once you have exited the editor you’ll see output similar to the following:

      Output

      service/ambassador edited

      Check svc1.your-domain using curl for the content-encoding header having value gzip:

      • curl --compressed -i http://svc1.example.com

      The output will be similar to this:

      Output

      HTTP/1.1 200 OK server: envoy date: Mon, 17 Jun 2019 22:25:35 GMT content-type: text/html last-modified: Tue, 21 May 2019 14:23:57 GMT accept-ranges: bytes x-geo-location: India vary: Accept-Encoding content-encoding: gzip transfer-encoding: chunked <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>

      Here you can see the default HTML page of Nginx with its response header showing that content-encoding of the received response is gzip compressed.

      You’ve added global configuration to Ambassador to enable GZIP configuration for selected content type responses across the API Gateway.

      Conclusion

      You have successfully set up an API Gateway for your Kubernetes cluster using Ambassador. You are now able to expose your apps using host- and path-based routing, custom headers, and global GZIP compression.

      For further information about the Ambassador annotations and configuration parameters, read Ambassador’s official documentation.



      Source link