Pattern matches in Haskell are based on matching specific data constructors, with underscores `_` as a "match anything" mechanism. So one way to achieve something like what you want is
veggieKebab :: Shishkebab -> Bool
veggieKebab Skewer = True
veggieKebab (Onion (shk)) = veggieKebab shk
veggieKebab (Tomato (shk)) = veggieKebab shk
veggieKebab _ = False
This works because the matches are considered in top-to-bottom order, so the last case only matches if all the others fail to.
I'm not sure if it helps to build insight or not, but if you look at the the types of your data constructors in GHCI, you get, for example:
λ> :t Onion
Onion :: Shishkebab -> Shishkebab
So even if you could pattern match as you wanted (veggieKebab (shkb (sk)) | (shkb == Onion)), you'd still be stuck with the problem of trying to compare two functions for equality, which isn't easy (and not something Haskell lets you do for arbitrary functions). You could get close to what you originally wrote by using a few more helper functions:
startsWithOnion :: Shishkebab -> Bool
startsWithOnion (Onion _) = True
startsWithOnion _ = False
startsWithTomato :: Shishkebab -> Bool
startsWithTomato (Tomato _) = True
startsWithTomato _ = False
restOfKebab :: Shishkebab -> Shishkebab
restOfKebab Skewer = Skewer
restOfKebab (Onion rst) = rst
restOfKebab (Tomato rst) = rst
restOfKebab (Lamb rst) = rst
veggieKebab :: Shishkebab -> Bool
veggieKebab Skewer = True
veggieKebab kebab | startsWithOnion kebab || startsWithTomato kebab = veggieKebab (restOfKebab kebab)
| otherwise = False